Skip to content

planner: tighten full-range fast path for index estimation#68474

Open
terry1purcell wants to merge 3 commits into
pingcap:masterfrom
terry1purcell:fullrangefix
Open

planner: tighten full-range fast path for index estimation#68474
terry1purcell wants to merge 3 commits into
pingcap:masterfrom
terry1purcell:fullrangefix

Conversation

@terry1purcell
Copy link
Copy Markdown
Contributor

@terry1purcell terry1purcell commented May 19, 2026

Two fixes raised in the release-8.5 cherry-pick review (PR #66695) that also apply on master:

  1. Move canSkipIndexEstimation ahead of IndexStatsIsInvalid so the full-range fast path short-circuits before IndexStatsIsInvalid queues an unnecessary async histogram load when the index stats are not fully loaded. Guarded by idx != nil so the pseudo fallback is preserved.

  2. Reject ranges with LowExclude or HighExclude in isFullRangeIncludingNulls. A range like (NULL, +inf) drops the NULL endpoint and shrinks the result, so it must not trigger the fast path.

Tighten TestCanSkipIndexEstimation to actually exercise these cases: model 10 NULL rows in the index histogram (NullCount=10) so the not-null estimate is strictly below RealtimeCount, switch the assertion to require.Less, and add a case covering (NULL, +inf) with an exclusive lower bound.

What problem does this PR solve?

Issue Number: ref #64791

Problem Summary:

What changed and how does it work?

Check List

Tests

  • Unit test
  • Integration test
  • Manual test (add detailed scripts or steps below)
  • No need to test
    • I checked and no code files have been changed.

Side effects

  • Performance regression: Consumes more CPU
  • Performance regression: Consumes more Memory
  • Breaking backward compatibility

Documentation

  • Affects user behaviors
  • Contains syntax changes
  • Contains variable changes
  • Contains experimental features
  • Changes MySQL compatibility

Release note

Please refer to Release Notes Language Style Guide to write a quality release note.

None

Summary by CodeRabbit

  • Bug Fixes

    • Improved cardinality estimation: planner now short-circuits earlier for eligible indexes and correctly rejects ranges with exclusive endpoints, preventing incorrect fast-path use and ensuring counts exclude endpoints like NULL when appropriate.
  • Tests

    • Tightened tests and updated plan expectations to verify the fast-path only applies to NULL-inclusive full ranges and async stats-loading behavior.

Review Change Stack

Two fixes raised in the release-8.5 cherry-pick review (PR pingcap#66695) that
also apply on master:

1. Move canSkipIndexEstimation ahead of IndexStatsIsInvalid so the
   full-range fast path short-circuits before IndexStatsIsInvalid
   queues an unnecessary async histogram load when the index stats are
   not fully loaded. Guarded by idx != nil so the pseudo fallback is
   preserved.

2. Reject ranges with LowExclude or HighExclude in
   isFullRangeIncludingNulls. A range like (NULL, +inf) drops the
   NULL endpoint and shrinks the result, so it must not trigger the
   fast path.

Tighten TestCanSkipIndexEstimation to actually exercise these cases:
model 10 NULL rows in the index histogram (NullCount=10) so the
not-null estimate is strictly below RealtimeCount, switch the
assertion to require.Less, and add a case covering (NULL, +inf) with
an exclusive lower bound.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ti-chi-bot ti-chi-bot Bot added the release-note-none Denotes a PR that doesn't merit a release note. label May 19, 2026
@pantheon-ai
Copy link
Copy Markdown

pantheon-ai Bot commented May 19, 2026

@terry1purcell I've received your pull request and will start the review. I'll conduct a thorough review covering code quality, potential issues, and implementation details.

⏳ This process typically takes 10-30 minutes depending on the complexity of the changes.

ℹ️ Learn more details on Pantheon AI.

@ti-chi-bot ti-chi-bot Bot added size/M Denotes a PR that changes 30-99 lines, ignoring generated files. sig/planner SIG: Planner labels May 19, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: f68df245-60ae-4eb9-948e-3fac77c54c65

📥 Commits

Reviewing files that changed from the base of the PR and between c13524f and 9452072.

📒 Files selected for processing (1)
  • pkg/planner/cardinality/selectivity_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/planner/cardinality/selectivity_test.go

📝 Walkthrough

Walkthrough

Moves the index-estimation fast-path earlier to return scaled realtime counts for inclusive full-range non-MV/non-partial indexes, tightens full-range NULL-boundary checks to reject exclusive bounds, and updates tests and EXPLAIN expectations to match the new short-circuiting behavior.

Changes

Index Cardinality Estimation

Layer / File(s) Summary
Fast-path relocation and boundary validation
pkg/planner/cardinality/row_count_index.go
GetRowCountByIndexRanges now short-circuits earlier using GetScaledRealtimeAndModifyCnt for qualifying non-MV, non-partial inclusive full-range indexes. isFullRangeIncludingNulls now rejects ranges with exclusive low or high bounds.
Test and EXPLAIN updates
pkg/planner/cardinality/selectivity_test.go, pkg/executor/test/analyzetest/analyze_test.go
TestCanSkipIndexEstimation builds mock stats with 50 non-NULL + 10 NULL rows, regenerates index-histogram keys from non-NULL values, and tightens assertions so the fast-path only applies to inclusive [NULL, +inf) ranges (which must return RealtimeCount and not enqueue async loading); other ranges (exclude-NULL, bounded, or exclusive endpoints) must produce estimates strictly less than RealtimeCount. TestAnalyzeMVIndex EXPLAIN expectations updated to show ia:allEvicted and j:unInitialized after async-loading emulation.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • hawkingrei
  • AilinKid

Poem

🐰 I hopped through NULLs and bounds so wide,
I nudged the fast-path to the earlier side,
Inclusive ranges now leap, exclusive stay shy,
Tests clap their paws, and explain lets out a sigh,
Carrots for CI—fast counts, no async try!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: tightening the full-range fast path for index estimation in the planner package.
Description check ✅ Passed The description covers the problem summary, changes made, and test updates. However, the Issue Number section is incomplete with only a 'ref' without the issue number explicitly stated.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@tiprow
Copy link
Copy Markdown

tiprow Bot commented May 19, 2026

Hi @terry1purcell. Thanks for your PR.

PRs from untrusted users cannot be marked as trusted with /ok-to-test in this repo meaning untrusted PR authors can never trigger tests themselves. Collaborators can still trigger tests on the PR using /test all.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

…eorder

LoadNeededHistograms no longer loads stats for non-MV indexes like ia
that were only touched as candidate access paths — the full-range
fast path now short-circuits before IndexStatsIsInvalid queues them
for async load. Update the section-3.3 expected plans to keep ia in
the partial-stats list, and clarify the section comment.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ti-chi-bot ti-chi-bot Bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels May 19, 2026
@ti-chi-bot
Copy link
Copy Markdown

ti-chi-bot Bot commented May 19, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign 0xpoe for approval. For more information see the Code Review Process.
Please ensure that each of them provides their approval before proceeding.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@terry1purcell
Copy link
Copy Markdown
Contributor Author

/ok-to-test

@ti-chi-bot ti-chi-bot Bot added the ok-to-test Indicates a PR is ready to be tested. label May 19, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 19, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 75.6766%. Comparing base (296420e) to head (9452072).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@               Coverage Diff                @@
##             master     #68474        +/-   ##
================================================
- Coverage   77.2806%   75.6766%   -1.6040%     
================================================
  Files          2010       2008         -2     
  Lines        555350     563899      +8549     
================================================
- Hits         429178     426740      -2438     
- Misses       125252     137039     +11787     
+ Partials        920        120       -800     
Flag Coverage Δ
integration 41.5378% <100.0000%> (+1.7448%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
dumpling 60.4679% <ø> (ø)
parser ∅ <ø> (∅)
br 49.9534% <ø> (-13.0557%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

… fast path

The previous test set the index to FullLoad, which made
IndexStatsIsInvalid a no-op for the async-load queue — so the test
would pass even if canSkipIndexEstimation were removed or if the
fast-path reorder were reverted.

Switch the mock index to NewStatsAllEvictedStatus so IndexStatsIsInvalid
would queue it for async load if it were ever reached, and assert that
AsyncLoadHistogramNeededItems does not contain the index after the
full-range call. This now fails if the fast path moves back below
IndexStatsIsInvalid. Switch sctx to the testkit's real session via
GetPlanCtx() since recordUsedItemStatsStatus needs a domain to resolve
the table when the stats are not FullLoad.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ok-to-test Indicates a PR is ready to be tested. release-note-none Denotes a PR that doesn't merit a release note. sig/planner SIG: Planner size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant