use of io.prestosql.sql.planner.optimizations.BeginTableWrite in project hetu-core by openlookeng.
the class HetuLogicalPlanner method plan.
@Override
public Plan plan(Analysis analysis, boolean skipStatsWithPlan, Stage stage) {
PlanNode root = planStatement(analysis, analysis.getStatement());
PlanNode.SkipOptRuleLevel optimizationLevel = APPLY_ALL_RULES;
planSanityChecker.validateIntermediatePlan(root, session, metadata, typeAnalyzer, planSymbolAllocator.getTypes(), warningCollector);
if (stage.ordinal() >= Stage.OPTIMIZED.ordinal()) {
for (PlanOptimizer optimizer : planOptimizers) {
if (OptimizerUtils.isEnabledLegacy(optimizer, session, root)) {
// We run it separately in the SqlQueryExecution
if (optimizer instanceof BeginTableWrite) {
continue;
}
if (OptimizerUtils.canApplyOptimizer(optimizer, optimizationLevel)) {
root = optimizer.optimize(root, session, planSymbolAllocator.getTypes(), planSymbolAllocator, idAllocator, warningCollector);
requireNonNull(root, format("%s returned a null plan", optimizer.getClass().getName()));
optimizationLevel = optimizationLevel == APPLY_ALL_RULES ? root.getSkipOptRuleLevel() : optimizationLevel;
}
}
}
}
if (stage.ordinal() >= Stage.OPTIMIZED_AND_VALIDATED.ordinal()) {
// make sure we produce a valid plan after optimizations run. This is mainly to catch programming errors
planSanityChecker.validateFinalPlan(root, session, metadata, typeAnalyzer, planSymbolAllocator.getTypes(), warningCollector);
}
TypeProvider types = planSymbolAllocator.getTypes();
// we calculate stats here only if need to show as part of EXPLAIN, otherwise not needed.
if (skipStatsWithPlan && isSkipAttachingStatsWithPlan(session)) {
return new Plan(root, types, StatsAndCosts.empty());
} else {
StatsProvider statsProvider = new CachingStatsProvider(statsCalculator, session, types);
CostProvider costProvider = new CachingCostProvider(costCalculator, statsProvider, Optional.empty(), session, types);
return new Plan(root, types, StatsAndCosts.create(root, statsProvider, costProvider));
}
}
use of io.prestosql.sql.planner.optimizations.BeginTableWrite in project hetu-core by openlookeng.
the class CachedSqlQueryExecution method createPlan.
@Override
protected Plan createPlan(Analysis analysis, Session session, List<PlanOptimizer> planOptimizers, PlanNodeIdAllocator idAllocator, Metadata metadata, TypeAnalyzer typeAnalyzer, StatsCalculator statsCalculator, CostCalculator costCalculator, WarningCollector warningCollector) {
Statement statement = analysis.getStatement();
// Get relevant Session properties which may affect the resulting execution plan
// Property to property value mapping
Map<String, Object> systemSessionProperties = new HashMap<>();
SystemSessionProperties sessionProperties = new SystemSessionProperties();
for (PropertyMetadata<?> property : sessionProperties.getSessionProperties()) {
systemSessionProperties.put(property.getName(), session.getSystemProperty(property.getName(), property.getJavaType()));
}
// if the original statement before rewriting is CreateIndex, set session to let connector know that pageMetadata should be enabled
if (analysis.getOriginalStatement() instanceof CreateIndex || analysis.getOriginalStatement() instanceof UpdateIndex) {
session.setPageMetadataEnabled(true);
}
// build list of fully qualified table names
List<String> tableNames = new ArrayList<>();
Map<String, TableStatistics> tableStatistics = new HashMap<>();
// Get column name to column type to detect column type changes between queries more easily
Map<String, Type> columnTypes = new HashMap<>();
// Cacheable conditions:
// 1. Caching must be enabled globally
// 2. Caching must be enabled in the session
// 3. There must not be any parameters in the query
// TODO: remove requirement for empty params and implement parameter rewrite
// 4. Methods in ConnectorTableHandle and ConnectorMetadata must be
// overwritten to allow access to fully qualified table names and column names
// 5. Statement must be an instance of Query and not contain CurrentX functions
boolean cacheable = this.cache.isPresent() && isExecutionPlanCacheEnabled(session) && analysis.getParameters().isEmpty() && validateAndExtractTableAndColumns(analysis, metadata, session, tableNames, tableStatistics, columnTypes) && isCacheable(statement) && // create index and update index should not be cached
(!(analysis.getOriginalStatement() instanceof CreateIndex || analysis.getOriginalStatement() instanceof UpdateIndex));
cacheable = cacheable && !tableNames.isEmpty();
if (!cacheable) {
return super.createPlan(analysis, session, planOptimizers, idAllocator, metadata, typeAnalyzer, statsCalculator, costCalculator, warningCollector);
}
List<String> optimizers = new ArrayList<>();
// build list of enabled optimizers and rules for cache key
for (PlanOptimizer planOptimizer : planOptimizers) {
if (planOptimizer instanceof IterativeOptimizer) {
IterativeOptimizer iterativeOptimizer = (IterativeOptimizer) planOptimizer;
Set<Rule<?>> rules = iterativeOptimizer.getRules();
for (Rule rule : rules) {
if (OptimizerUtils.isEnabledRule(rule, session)) {
optimizers.add(rule.getClass().getSimpleName());
}
}
} else {
if (OptimizerUtils.isEnabledLegacy(planOptimizer, session)) {
optimizers.add(planOptimizer.getClass().getSimpleName());
}
}
}
Set<String> connectors = tableNames.stream().map(table -> table.substring(0, table.indexOf("."))).collect(Collectors.toSet());
connectors.stream().forEach(connector -> {
for (Map.Entry<String, String> property : session.getConnectorProperties(new CatalogName(connector)).entrySet()) {
systemSessionProperties.put(connector + "." + property.getKey(), property.getValue());
}
});
Plan plan;
// TODO: Traverse the statement to build the key then combine tables/optimizers.. etc
int key = SqlQueryExecutionCacheKeyGenerator.buildKey((Query) statement, tableNames, optimizers, columnTypes, session.getTimeZoneKey(), systemSessionProperties);
CachedSqlQueryExecutionPlan cachedPlan = this.cache.get().getIfPresent(key);
HetuLogicalPlanner logicalPlanner = new HetuLogicalPlanner(session, planOptimizers, idAllocator, metadata, typeAnalyzer, statsCalculator, costCalculator, warningCollector);
PlanNode root;
plan = cachedPlan != null ? cachedPlan.getPlan() : null;
// that rely on system time
if (plan != null && cachedPlan.getTimeZoneKey().equals(session.getTimeZoneKey()) && cachedPlan.getStatement().equals(statement) && session.getTransactionId().isPresent() && cachedPlan.getIdentity().getUser().equals(session.getIdentity().getUser())) {
// TODO: traverse the statement and accept partial match
root = plan.getRoot();
boolean isValidCachePlan = tablesMatch(root, analysis.getTables());
try {
if (!isEqualBasicStatistics(cachedPlan.getTableStatistics(), tableStatistics, tableNames) || !isValidCachePlan) {
for (TableHandle tableHandle : analysis.getTables()) {
tableStatistics.replace(tableHandle.getFullyQualifiedName(), metadata.getTableStatistics(session, tableHandle, Constraint.alwaysTrue(), true));
}
if (!cachedPlan.getTableStatistics().equals(tableStatistics) || !isValidCachePlan) {
// Table have changed, therfore the cached plan may no longer be applicable
throw new NoSuchElementException();
}
}
// TableScanNode may contain the old transaction id.
// The following logic rewrites the logical plan by replacing the TableScanNode with a new TableScanNode which
// contains the new transaction id from session.
root = SimplePlanRewriter.rewriteWith(new TableHandleRewriter(session, analysis, metadata), root);
} catch (NoSuchElementException e) {
// Cached plan is outdated
// invalidate cache
this.cache.get().invalidateAll();
// Build a new plan
plan = createAndCachePlan(key, logicalPlanner, statement, tableNames, tableStatistics, optimizers, analysis, columnTypes, systemSessionProperties);
root = plan.getRoot();
}
} else {
// Build a new plan
for (TableHandle tableHandle : analysis.getTables()) {
tableStatistics.replace(tableHandle.getFullyQualifiedName(), metadata.getTableStatistics(session, tableHandle, Constraint.alwaysTrue(), true));
}
plan = createAndCachePlan(key, logicalPlanner, statement, tableNames, tableStatistics, optimizers, analysis, columnTypes, systemSessionProperties);
root = plan.getRoot();
}
// BeginTableWrite optimizer must be run at the end as the last optimization
// due to a hack Hetu community added which also serves to updates
// metadata in the nodes
root = this.beginTableWrite.optimize(root, session, null, null, null, null);
plan = update(plan, root);
return plan;
}
Aggregations