{"record":{"id":"ec6488de749d968b","repo":"prestodb/presto","slug":"optimizer-timeout","errorCode":"OPTIMIZER_TIMEOUT","errorMessage":"The optimizer exhausted the time limit of %d ms","messagePattern":"The optimizer exhausted the time limit of (.+?) ms","errorType":"error_code","errorClass":"PrestoException","httpStatus":null,"severity":"error","filePath":"presto-main-base/src/main/java/com/facebook/presto/sql/planner/iterative/IterativeOptimizer.java","lineNumber":445,"sourceCode":"            this.lookup = lookup;\n            this.idAllocator = idAllocator;\n            this.variableAllocator = variableAllocator;\n            this.startTimeInNanos = startTimeInNanos;\n            this.timeoutInMilliseconds = timeoutInMilliseconds;\n            this.session = session;\n            this.warningCollector = warningCollector;\n            this.costProvider = costProvider;\n            this.statsProvider = statsProvider;\n            this.metadata = metadata;\n            this.types = types;\n            this.rulesTriggered = new HashSet<>();\n            this.rulesApplicable = new HashSet<>();\n        }\n\n        public void checkTimeoutNotExhausted()\n        {\n            if ((NANOSECONDS.toMillis(System.nanoTime() - startTimeInNanos)) >= timeoutInMilliseconds) {\n                throw new PrestoException(OPTIMIZER_TIMEOUT, format(\"The optimizer exhausted the time limit of %d ms\", timeoutInMilliseconds));\n            }\n        }\n\n        public void addRulesTriggered(String rule, PlanNode oldNode, PlanNode newNode, boolean isCostBased, String statsSource)\n        {\n            Optional<String> before = Optional.empty();\n            Optional<String> after = Optional.empty();\n\n            if (SystemSessionProperties.isVerboseOptimizerResults(session, rule)) {\n                before = Optional.of(PlannerUtils.getPlanString(oldNode, session, types, metadata, false));\n                after = Optional.of(PlannerUtils.getPlanString(newNode, session, types, metadata, false));\n            }\n\n            rulesTriggered.add(new RuleTriggered(rule, before, after, isCostBased, statsSource));\n        }\n\n        public void addRulesApplicable(String rule)\n        {","sourceCodeStart":427,"sourceCodeEnd":463,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-main-base/src/main/java/com/facebook/presto/sql/planner/iterative/IterativeOptimizer.java#L427-L463","documentation":"The iterative optimizer enforces a wall-clock time budget per query optimization. When rule exploration exceeds the configured timeout, Presto aborts optimization with OPTIMIZER_TIMEOUT rather than hanging.","triggerScenarios":"Running a query whose plan exploration (rule applications in the memo) exceeds the session/system 'optimizer-timeout' limit in milliseconds.","commonSituations":"Very large or highly nested queries with many join reorderings; optimizer-timeout set too low for complex analytical queries; pathological queries causing rule explosion.","solutions":["Increase the optimizer timeout: SET SESSION optimizer_timeout = '60s' (or raise it in properties config)","Simplify the query (fewer joins/subqueries, add explicit joins instead of relying on reordering)","Reduce applicable rules via session optimizer feature flags, or check for query patterns that trigger rule explosion"],"exampleFix":"// before\nSELECT ... /* huge 30+ table join */;\n// after\nSET SESSION optimizer_timeout = '120s';\nSELECT ... /* join split into CTEs or pre-aggregated */;","handlingStrategy":"retry","validationCode":"// estimate complexity before running: count joins/subqueries\nconst isComplex = (sql.match(/\\bJOIN\\b/gi) || []).length > 15;\nif (isComplex) setSessionProperty('optimizer_timeout', '120s');","typeGuard":"null","tryCatchPattern":"try {\n    runQuery(sql);\n} catch (PrestoException e) {\n    if (e.getErrorCode() == OPTIMIZER_TIMEOUT.toErrorCode()) {\n        setSessionProperty(\"optimizer_timeout\", \"300s\");\n        return retryQuery(sql);\n    }\n    throw e;\n}","preventionTips":["Set a generous optimizer_timeout for analytical workloads","Keep join counts per query manageable; split very large joins","Monitor for queries repeatedly hitting the optimizer timeout"],"tags":["optimizer","timeout","performance"],"backgroundTag":"optimizer-timeout-exceeded","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}