Skip to content

refactor: make Recursive CTE execution more streaming-oriented#19545

Draft
KKould wants to merge 16 commits intodatabendlabs:mainfrom
KKould:refacotr/r_cte_stream
Draft

refactor: make Recursive CTE execution more streaming-oriented#19545
KKould wants to merge 16 commits intodatabendlabs:mainfrom
KKould:refacotr/r_cte_stream

Conversation

@KKould
Copy link
Member

@KKould KKould commented Mar 12, 2026

I hereby agree to the terms of the CLA available at: https://docs.databend.com/dev/policies/cla/

Summary

This PR was originally intended to address the issue where Databend could not execute a Sudoku query described in #18237

However, the surface-level error reported in that issue has already been fixed by #19212

While working on this problem, this PR added support for UnionAll and RecursiveCteScan in the SubqueryDecorrelatorOptimizer within flatten_plan. During testing with deeply recursive cases such as Sudoku, it was discovered that the current implementation of RecursiveCteScan performs a large amount of intermediate materialization. In scenarios with deep recursion, these intermediate results accumulate rapidly, causing query memory usage to grow dramatically, which eventually prevents the query from completing and may even lead to a system crash.

Therefore, this PR prioritizes a refactoring of RecursiveCteScan. The goal is to make its execution more streaming-oriented, reducing unnecessary intermediate materialization and repeated execution during the query process. This helps control memory usage and enables deeply recursive queries like Sudoku to run more reliably.

Key Fixes

  • Make rCTE internal table names stably unique per query + logical rCTE identity
    Previously, rCTE internal table names were only unique within a query. This caused duplicated recursive CTE branches produced by decorrelation to run independently on different internal tables.
    The change makes the naming stable per query + logical rCTE identity, ensuring duplicated branches of the same recursive CTE share the same internal tables instead of executing separately.
  • Introduce logical_recursive_cte_id and propagate it from logical plan to execution
    A logical_recursive_cte_id is introduced and passed through the logical plan → physical plan → execution layer.
    This allows the executor to determine that multiple operators belong to the same recursive CTE, instead of inferring it indirectly from table_name or alias.
  • Promote runtime id from local QueryContext state to shared state
    The runtime id was previously stored only within a single QueryContext.
    It is now promoted to shared state, allowing subqueries or child contexts to retrieve the same runtime id for the same logical rCTE.
    This is essential for enabling reuse in correlated subqueries.

Execution Layer Improvements

  • Remove the old exec_id semantics
    RecursiveCteScan now operates through reader registration and block fetching, instead of being tightly coupled to a single execution instance.
  • Redesign the memory table structure
    The memory table has been changed from a flat Vec to a generation/frontier + reader cursor model.
    This explicitly tracks:
    • Which iteration a block belongs to: generations
    • Which iteration each reader is consuming: readers
    • The currently active iteration: active_generation
    • When old generations can be cleaned: during generation switches
  • Make RecursiveCteScan pull blocks incrementally
    Instead of concatenating an entire iteration and emitting it at once, the scan now pulls data block by block via:
    take_one_block(reader_id)
  • Reduce memory usage and improve streaming behavior for recursive CTE execution

Tips:

  • It's still not possible to complete the full Sudoku SQL in Bug: using recursive CTE to solve sudoku returns error #18237. However, this pull request avoids the original crash caused by excessive memory usage during query execution. But optimizations are still needed beyond RCTE to fully resolve this issue.
  • the commit: ea2115e,It only stabilizes the sqllogictests hybrid test harness so CI failures are less likely to come from TTC/databend startup races.

Example:

WITH RECURSIVE digits(z, lp) AS (
    SELECT '1', 1
    UNION ALL SELECT CAST(lp+1 AS TEXT), lp+1 FROM digits WHERE lp<3
),
x(s, ind) AS (
    SELECT '..', 1
    UNION ALL
    SELECT
        substr(s, 1, ind-1) || z || substr(s, ind+1),
        instr(substr(s, 1, ind-1) || z || substr(s, ind+1), '.')
    FROM x, digits AS z
    WHERE ind>0
      AND NOT EXISTS (
        SELECT 1 FROM digits AS lp
        WHERE z.z = '1' AND lp.lp = 2
      )
)
SELECT s, ind FROM x ORDER BY s, ind;

Tests

  • Unit Test
  • Logic Test
  • Benchmark Test
  • No Test - Explain why

Type of change

  • Bug Fix (non-breaking change which fixes an issue)
  • New Feature (non-breaking change which adds functionality)
  • Breaking Change (fix or feature that could cause existing functionality not to work as expected)
  • Documentation Update
  • Refactoring
  • Performance Improvement
  • Other (please describe):

This change is Reviewable

@KKould KKould changed the title Refacotr/Recursive CTE streaming execution refactor: Recursive CTE streaming execution Mar 12, 2026
@github-actions github-actions bot added the pr-refactor this PR changes the code base without new features or bugfix label Mar 12, 2026
@KKould KKould force-pushed the refacotr/r_cte_stream branch from 1c0f22f to 930ea96 Compare March 12, 2026 10:33
@KKould KKould requested review from SkyFan2002 and sundy-li and removed request for SkyFan2002 March 12, 2026 10:35
@KKould KKould self-assigned this Mar 12, 2026
@KKould KKould force-pushed the refacotr/r_cte_stream branch from 83676b2 to 66f55aa Compare March 12, 2026 11:24
@KKould KKould marked this pull request as ready for review March 13, 2026 04:30
@KKould KKould marked this pull request as draft March 13, 2026 04:30
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f3ae46dbf6

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@KKould
Copy link
Member Author

KKould commented Mar 13, 2026

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 92de3e8860

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@KKould
Copy link
Member Author

KKould commented Mar 13, 2026

@codex review

@KKould KKould force-pushed the refacotr/r_cte_stream branch from b192ab2 to 18df7e1 Compare March 14, 2026 14:13
@KKould KKould changed the title refactor: Recursive CTE streaming execution Refactor: make Recursive CTE execution more streaming-oriented Mar 14, 2026
@KKould KKould changed the title Refactor: make Recursive CTE execution more streaming-oriented refactor: make Recursive CTE execution more streaming-oriented Mar 14, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Mar 14, 2026

🤖 CI Job Analysis

Workflow: 23092130459

📊 Summary

  • Total Jobs: 24
  • Failed Jobs: 3
  • Retryable: 0
  • Code Issues: 3

NO RETRY NEEDED

All failures appear to be code/test issues requiring manual fixes.

🔍 Job Details

  • linux / check: Not retryable (Code/Test)
  • linux / test_unit: Not retryable (Code/Test)
  • linux / build: Not retryable (Code/Test)

🤖 About

Automated analysis using job annotations to distinguish infrastructure issues (auto-retried) from code/test issues (manual fixes needed).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr-refactor this PR changes the code base without new features or bugfix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant