feat(query): cache parameterized logical plans#20152
Draft
dbsid wants to merge 1 commit into
Draft
Conversation
Reuse bound logical plan templates across queries that differ only in predicate literals. Re-inject typed values and rerun optimization so literal-sensitive rewrites and pruning remain fresh. Keep exact optimized plans as the first-level cache, validate catalog and table state, and invalidate affected entries after mutations.
dbsid
force-pushed
the
codex/parameterized-planner-cache
branch
from
July 15, 2026 04:18
202bda3 to
58ca1fd
Compare
Contributor
🤖 CI Job Analysis (Retry 1)
📊 Summary
❌ NO RETRY NEEDEDAll failures appear to be code/test issues requiring manual fixes. 🔍 Job Details
🤖 AboutAutomated analysis using job annotations to distinguish infrastructure issues (auto-retried) from code/test issues (manual fixes needed). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
I hereby agree to the terms of the CLA available at: https://docs.databend.com/dev/policies/cla/
Summary
This PR extracts the planner-cache work from #20144. It does not include ordered top-k, PresortedMerge, page statistics, or their settings.
It adds a bounded two-level logical planner cache:
Only logical planning is cached. Physical planning, block pruning, and execution are performed for every query, so different predicate values still produce value-specific physical plans and scan ranges. The query-result-cache key continues to use the current query's original formatted AST.
Parameterized predicates cover comparisons, IN, BETWEEN, LIKE/regexp, and IS DISTINCT FROM. LIMIT and OFFSET remain part of the template shape and are not parameterized. Unsupported plans fall back to the normal AST bind path. User-written calls using the internal parameter-marker name disable parameterization defensively.
Cache isolation and validation include tenant, catalog, database, optimizer-relevant settings, variables, security context, table IDs/sequences/schemas/snapshots, and security policies. A table-snapshot mismatch evicts the local stale entry before reuse, including when the metadata change was made by another query node. Table functions, external locations, async functions, and other unsafe dependencies are not cached.
Successful DML invalidates entries for affected table IDs. Successful catalog DDL advances the DDL generation and clears the cache, including table/database/index/policy/tag/sequence/dictionary paths. Mutation generations close concurrent insert/invalidate races.
The enable_planner_cache setting supports both session SET and persistent SET GLOBAL scopes. The cache uses a byte-bounded LRU configured by cache.planner_cache_max_bytes, with a 512 MiB default. The previous standalone physical-plan-cache experiment and enable_standalone_fast_planner_cache setting are intentionally not included.
No-lazy benchmark
Authoritative binaries:
Environment: one standalone query node on web3-i4i, on-disk data cache enabled, lazy_read_threshold=0, query-result cache disabled, planner cache enabled, distributed pruning disabled, max_threads=16, 5 concurrent clients, and fixed seed 2026071305.
The test used two interleaved baseline/final rounds. For each process, Q1/Q2/Flex were all warmed first (400 iterations per worker), then each query ran 3,000 measured requests. This preserves mixed-query exact-cache pressure instead of making one query's exact plans artificially hot immediately before measurement.
All 36,000 measured requests succeeded. Each baseline round recorded 15,030 accesses / 1,103 misses / 13,927 hits. Each final round recorded 15,630 accesses / 603 misses / 15,027 hits; the additional template lookup path produced 597 hits and only 3 misses across the 600 distinct exact-SQL misses.
A query-local hot-cache control warmed and measured each query consecutively. All mean/p95/QPS changes stayed within 0.6%, showing no material regression when every exact plan already fits and is hot.
Tests
Validation performed on web3-i4i:
Type of change
This change is