diff --git a/presto-docs/src/main/sphinx/admin/properties.rst b/presto-docs/src/main/sphinx/admin/properties.rst index 0435d11c2966..2f51b3a40186 100644 --- a/presto-docs/src/main/sphinx/admin/properties.rst +++ b/presto-docs/src/main/sphinx/admin/properties.rst @@ -53,6 +53,18 @@ output data set is not skewed in order to avoid the overhead of hashing and redistributing all the data across the network. This can also be specified on a per-query basis using the ``redistribute_writes`` session property. +``query-execution-fail-fast-enabled`` +^^^^^^^^^^^^^^^^^^^^^^^ + +* **Type:** ``boolean`` +* **Default value:** ``false`` + +This property enables the eager building and validation of a logical plan. +When enabled, the logical plan can be built and validated before execution +begins so that any errors or incompatibilities in the plan will cause the +query to fail before resources are allocated and quickly inform the user +of the error. + .. _tuning-memory: Memory Management Properties diff --git a/presto-main/src/main/java/com/facebook/presto/SystemSessionProperties.java b/presto-main/src/main/java/com/facebook/presto/SystemSessionProperties.java index 1afbc272f89b..65cad2560a81 100644 --- a/presto-main/src/main/java/com/facebook/presto/SystemSessionProperties.java +++ b/presto-main/src/main/java/com/facebook/presto/SystemSessionProperties.java @@ -331,6 +331,7 @@ public final class SystemSessionProperties public static final String REWRITE_EXPRESSION_WITH_CONSTANT_EXPRESSION = "rewrite_expression_with_constant_expression"; public static final String PRINT_ESTIMATED_STATS_FROM_CACHE = "print_estimated_stats_from_cache"; public static final String REMOVE_CROSS_JOIN_WITH_CONSTANT_SINGLE_ROW_INPUT = "remove_cross_join_with_constant_single_row_input"; + public static final String QUERY_EXECUTION_FAIL_FAST_ENABLED = "query_execution_fail_fast_enabled"; // TODO: Native execution related session properties that are temporarily put here. They will be relocated in the future. public static final String NATIVE_SIMPLIFIED_EXPRESSION_EVALUATION_ENABLED = "native_simplified_expression_evaluation_enabled"; @@ -2010,6 +2011,11 @@ public SystemSessionProperties( "If one input of the cross join is a single row with constant value, remove this cross join and replace with a project node", featuresConfig.isRemoveCrossJoinWithSingleConstantRow(), false), + booleanProperty( + QUERY_EXECUTION_FAIL_FAST_ENABLED, + "Enable eager building and validation of logical plan before execution", + featuresConfig.isQueryExecutionFailFastEnabled(), + false), new PropertyMetadata<>( DEFAULT_VIEW_SECURITY_MODE, format("Set default view security mode. Options are: %s", @@ -3336,6 +3342,11 @@ public static boolean isRewriteExpressionWithConstantEnabled(Session session) return session.getSystemProperty(REWRITE_EXPRESSION_WITH_CONSTANT_EXPRESSION, Boolean.class); } + public static boolean isQueryExecutionFailFastEnabled(Session session) + { + return session.getSystemProperty(QUERY_EXECUTION_FAIL_FAST_ENABLED, Boolean.class); + } + public static CreateView.Security getDefaultViewSecurityMode(Session session) { return session.getSystemProperty(DEFAULT_VIEW_SECURITY_MODE, CreateView.Security.class); diff --git a/presto-main/src/main/java/com/facebook/presto/execution/SqlQueryExecution.java b/presto-main/src/main/java/com/facebook/presto/execution/SqlQueryExecution.java index 403b3de1ce75..4d2034c05515 100644 --- a/presto-main/src/main/java/com/facebook/presto/execution/SqlQueryExecution.java +++ b/presto-main/src/main/java/com/facebook/presto/execution/SqlQueryExecution.java @@ -75,6 +75,7 @@ import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.atomic.AtomicReference; @@ -83,6 +84,7 @@ import static com.facebook.presto.SystemSessionProperties.getExecutionPolicy; import static com.facebook.presto.SystemSessionProperties.getQueryAnalyzerTimeout; import static com.facebook.presto.SystemSessionProperties.isLogInvokedFunctionNamesEnabled; +import static com.facebook.presto.SystemSessionProperties.isQueryExecutionFailFastEnabled; import static com.facebook.presto.SystemSessionProperties.isSpoolingOutputBufferEnabled; import static com.facebook.presto.common.RuntimeMetricName.FRAGMENT_PLAN_TIME_NANOS; import static com.facebook.presto.common.RuntimeMetricName.GET_CANONICAL_INFO_TIME_NANOS; @@ -141,6 +143,7 @@ public class SqlQueryExecution private final PlanCanonicalInfoProvider planCanonicalInfoProvider; private final QueryAnalysis queryAnalysis; private final AnalyzerContext analyzerContext; + private final CompletableFuture planFuture; private SqlQueryExecution( QueryAnalyzer queryAnalyzer, @@ -243,6 +246,9 @@ private SqlQueryExecution( } } } + + // Optionally build and validate plan immediately, before execution begins + planFuture = isQueryExecutionFailFastEnabled(getSession()) ? createLogicalPlanAsync() : null; } } @@ -461,7 +467,7 @@ public void start() timeoutThreadExecutor, getQueryAnalyzerTimeout(getSession()))) { // create logical plan for the query - plan = createLogicalPlanAndOptimize(); + plan = planFuture == null ? createLogicalPlanAndOptimize() : planFuture.get(); } metadata.beginQuery(getSession(), plan.getConnectors()); @@ -528,6 +534,11 @@ public void addFinalQueryInfoListener(StateChangeListener stateChange stateMachine.addQueryInfoStateChangeListener(stateChangeListener); } + private CompletableFuture createLogicalPlanAsync() + { + return CompletableFuture.supplyAsync(this::createLogicalPlanAndOptimize, this.queryExecutor); + } + private PlanRoot createLogicalPlanAndOptimize() { try { diff --git a/presto-main/src/main/java/com/facebook/presto/sql/analyzer/FeaturesConfig.java b/presto-main/src/main/java/com/facebook/presto/sql/analyzer/FeaturesConfig.java index c88271e97dd5..fa41d7d36808 100644 --- a/presto-main/src/main/java/com/facebook/presto/sql/analyzer/FeaturesConfig.java +++ b/presto-main/src/main/java/com/facebook/presto/sql/analyzer/FeaturesConfig.java @@ -296,6 +296,8 @@ public class FeaturesConfig private boolean isInlineProjectionsOnValuesEnabled; + private boolean queryExecutionFailFastEnabled; + public enum PartitioningPrecisionStrategy { // Let Presto decide when to repartition @@ -2969,4 +2971,17 @@ public FeaturesConfig setInlineProjectionsOnValues(boolean isInlineProjectionsOn this.isInlineProjectionsOnValuesEnabled = isInlineProjectionsOnValuesEnabled; return this; } + + @Config("query-execution-fail-fast-enabled") + @ConfigDescription("Enable eager building and validation of logical plan before execution") + public FeaturesConfig setQueryExecutionFailFastEnabled(boolean queryExecutionFailFastEnabled) + { + this.queryExecutionFailFastEnabled = queryExecutionFailFastEnabled; + return this; + } + + public boolean isQueryExecutionFailFastEnabled() + { + return this.queryExecutionFailFastEnabled; + } }