Skip to content

planner/core: discourage degenerate index joins when probe rows approach a full scan | tidb-test=pr/2747 - #68557

Merged
ti-chi-bot[bot] merged 20 commits into
pingcap:release-8.5-20251125-v8.5.4from
guo-shaoge:cp_v8.5.4-20260329_refine_cost_indexjoin_hashjoin
May 22, 2026
Merged

planner/core: discourage degenerate index joins when probe rows approach a full scan | tidb-test=pr/2747#68557
ti-chi-bot[bot] merged 20 commits into
pingcap:release-8.5-20251125-v8.5.4from
guo-shaoge:cp_v8.5.4-20260329_refine_cost_indexjoin_hashjoin

Conversation

@guo-shaoge

@guo-shaoge guo-shaoge commented May 21, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: close #67610

Problem Summary: maunally cherry pick #67646

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

  • New Features

    • Added a global/session optimizer setting to control the max index-join scan-rows ratio (default 0.0).
  • Behavior

    • Optimizer prunes index-join candidates when estimated scan-row ratios favor hash join; query hints forcing index/hash join are still honored.
  • Tests

    • Added regression tests and updated many expected EXPLAIN/plan outputs to validate join selection across ratio values.
  • Chores

    • Updated test fixtures and increased test sharding granularity.

Review Change Stack

…ach a full scan

Signed-off-by: guo-shaoge <shaoge1994@163.com>
@ti-chi-bot ti-chi-bot Bot added 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. labels May 21, 2026
@coderabbitai

coderabbitai Bot commented May 21, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a sysvar to control max index-join scan-rows ratio, implements pruning thresholds/helpers, threads an enable flag through index-join enumeration to early-prune expensive index-join candidates when appropriate, and updates tests and expected-plan fixtures.

Changes

Index-Join Scan-Ratio Pruning

Layer / File(s) Summary
System variable wiring
pkg/sessionctx/variable/tidb_vars.go, pkg/sessionctx/variable/session.go, pkg/sessionctx/variable/sysvar.go
Adds TiDBOptIndexJoinMaxScanRowsRatio and DefOptIndexJoinMaxScanRowsRatio, adds SessionVars.IndexJoinMaxScanRowsRatio, and registers the sysvar in defaultSysVars.
Pruning thresholds and helper functions
pkg/planner/core/exhaust_physical_plans.go
Defines indexJoinPruneMinProbeRows/indexJoinPruneMinBuildRows and adds helpers getProbeFullScanRowCount, isPseudoStats, and shouldPruneIndexJoinByScanRatio.
getIndexJoinByOuterIdx pruning decision
pkg/planner/core/exhaust_physical_plans.go
Extends getIndexJoinByOuterIdx with enableRatioPrune; computes outer build stats and early-returns nil when pruning indicates index-join scans exceed hash-join scan volume.
tryToGetIndexJoin threading and detection
pkg/planner/core/exhaust_physical_plans.go
Adds hasForceIndexJoinFamilyHint, extends tryToGetIndexJoin to accept enableRatioPrune, and threads the flag to both outer-side calls; updates failpoint usage.
exhaustPhysicalPlans4LogicalJoin orchestration
pkg/planner/core/exhaust_physical_plans.go
Moves hash-join enumeration earlier, short-circuits on forced-hash cases, enables ratio pruning for index-join enumeration when hash joins exist and no forced index-join hint family is present, and handles forced index-join early return.
Test coverage and testdata
pkg/planner/core/plan_cost_ver2_test.go, pkg/planner/core/casetest/cbotest/*, pkg/planner/core/casetest/*, pkg/executor/testdata/*, tests/integrationtest/*
Adds a test block verifying IndexJoin selection across tidb_opt_index_join_max_scan_rows_ratio values, introduces TestAnalyzeSuiteRegression and its JSON fixtures, and updates numerous expected-plan/testdata files to reflect renumbered nodes and ratio-driven plan differences.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • pingcap/tidb#67646: Implements similar index-join/index-hash-join scan-ratio pruning using the tidb_opt_index_join_max_scan_rows_ratio sysvar.

Suggested labels

ok-to-test, approved, lgtm, cherry-pick-approved, type/cherry-pick-for-release-8.5-20251125-v8.5.4

Suggested reviewers

  • qw4990
  • AilinKid
  • terry1purcell

Poem

🐰 I count each probe and threshold with a hop,
When index scans swell, I whisper "stop."
A sysvar set, a prune on costly tries,
Tests refreshed and node-ids renamed — planner-wise.
Hooray for tidy hops and fewer wasted tries!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning Description is incomplete. Required 'What changed and how does it work?' section is empty. However, it does reference issue #67610 and indicates unit tests were included. Complete the 'What changed and how does it work?' section with a clear explanation of the implementation approach and design decisions.
Docstring Coverage ⚠️ Warning Docstring coverage is 29.41% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The code changes fully address issue #67610's objective: they implement ratio-based pruning to discourage degenerate index joins when probe rows approach full scans by comparing estimated index-join scan costs against hash-join alternatives.
Out of Scope Changes check ✅ Passed All code changes are within scope: core planner logic for index-join pruning, session variables for configuration, and test cases for validation. Test output updates and Bazel configuration are expected side-effects.
Title check ✅ Passed The PR title accurately describes the main change: introducing a pruning mechanism to discourage index joins when probe rows approach a full scan, which is reflected in the addition of scan-ratio based pruning logic in exhaust_physical_plans.go.

✏️ 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
pkg/planner/core/exhaust_physical_plans.go (1)

48-51: 💤 Low value

Consider documenting the rationale for these threshold values.

These magic numbers drive the pruning heuristic but lack comments explaining why 100K and 100 were chosen. A brief note about their origin (empirical tuning, benchmark results, or theoretical basis) would help future maintainers understand when these might need adjustment.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/planner/core/exhaust_physical_plans.go` around lines 48 - 51, Add short
explanatory comments above the constants indexJoinPruneMinProbeRows and
indexJoinPruneMinBuildRows describing why these thresholds (100000.0 and 100.0)
were chosen (e.g., empirical tuning, benchmark results, or theoretical
reasoning), note the units/meaning (probe rows vs build rows), and mention when
they should be revisited (tests/benchmarks or workload change); reference the
two constant names in the comment so future maintainers can trace the heuristic
origin and any supporting benchmark or issue ID.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/planner/core/plan_cost_ver2_test.go`:
- Around line 637-658: The current block only validates hint precedence because
the queries use the /*+ INL_JOIN(i) */ hint; add an unhinted join explain to
prove ratio-driven pruning: run tk.MustQuery("explain format=verbose select *
from t_outer o straight_join t_inner i on o.b = i.b") and capture rs, then
assert plan selection changes (e.g., require.NotContains(t, rs[0][0].(string),
"IndexJoin") when tk.MustExec("set
@@session.tidb_opt_index_join_max_scan_rows_ratio=0") and require.Contains(t,
rs[0][0].(string), "IndexJoin") after tk.MustExec("set
@@session.tidb_opt_index_join_max_scan_rows_ratio=0.8"); finally after resetting
with tk.MustExec("set
@@session.tidb_opt_index_join_max_scan_rows_ratio=default") add an assertion
that the unhinted plan returns to the default expected choice to cover
regression.

In `@pkg/sessionctx/variable/sysvar.go`:
- Around line 2125-2128: The TiDBOptIndexJoinMaxScanRowsRatio sysvar incorrectly
uses MaxValue: math.MaxUint64 for a ratio; update the sysvar definition (symbol
TiDBOptIndexJoinMaxScanRowsRatio) to use a sensible upper bound (e.g., MaxValue:
1.0) consistent with other ratio vars, or if this value is meant to be a
percentage choose a clearer max (e.g., 100) and consider renaming accordingly;
ensure the SessionVars field IndexJoinMaxScanRowsRatio and default
DefOptIndexJoinMaxScanRowsRatio remain compatible and that the setter
tidbOptFloat64(val, DefOptIndexJoinMaxScanRowsRatio) behavior is preserved.

---

Nitpick comments:
In `@pkg/planner/core/exhaust_physical_plans.go`:
- Around line 48-51: Add short explanatory comments above the constants
indexJoinPruneMinProbeRows and indexJoinPruneMinBuildRows describing why these
thresholds (100000.0 and 100.0) were chosen (e.g., empirical tuning, benchmark
results, or theoretical reasoning), note the units/meaning (probe rows vs build
rows), and mention when they should be revisited (tests/benchmarks or workload
change); reference the two constant names in the comment so future maintainers
can trace the heuristic origin and any supporting benchmark or issue ID.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d9b18008-2bea-4b27-a940-d608c492cfbc

📥 Commits

Reviewing files that changed from the base of the PR and between 2389a2f and a5615ab.

📒 Files selected for processing (5)
  • pkg/planner/core/exhaust_physical_plans.go
  • pkg/planner/core/plan_cost_ver2_test.go
  • pkg/sessionctx/variable/session.go
  • pkg/sessionctx/variable/sysvar.go
  • pkg/sessionctx/variable/tidb_vars.go

Comment on lines +637 to +658
// Test IndexJoin scan ratio threshold
tk.MustExec("drop table if exists t_outer, t_inner")
tk.MustExec("create table t_outer(a int primary key, b int, key(b))")
tk.MustExec("create table t_inner(a int primary key, b int, key(b))")
tk.MustExec("insert into t_outer values (1,1),(2,2),(3,3),(4,4),(5,5)")
tk.MustExec("insert into t_inner values (1,1),(2,2),(3,3),(4,4),(5,5)")
tk.MustExec("analyze table t_outer, t_inner")
tk.MustExec("set @@session.tidb_opt_hash_join_cost_factor=1")
tk.MustExec("set @@session.tidb_opt_merge_join_cost_factor=100")
tk.MustExec("set @@session.tidb_opt_index_join_cost_factor=1")
tk.MustExec("set @@session.tidb_opt_index_join_max_scan_rows_ratio=0")
rs = tk.MustQuery("explain format=verbose select /*+ INL_JOIN(i) */ * from t_outer o straight_join t_inner i on o.b = i.b").Rows()
require.Contains(t, rs[0][0].(string), "IndexJoin")
tk.MustExec("set @@session.tidb_opt_index_join_max_scan_rows_ratio=0.8")
rs = tk.MustQuery("explain format=verbose select /*+ INL_JOIN(i) */ * from t_outer o straight_join t_inner i on o.b = i.b").Rows()
require.Contains(t, rs[0][0].(string), "IndexJoin")
tk.MustExec("set @@session.tidb_opt_index_join_max_scan_rows_ratio=default")
tk.MustExec("set @@session.tidb_opt_hash_join_cost_factor=default")
tk.MustExec("set @@session.tidb_opt_merge_join_cost_factor=default")

// Reset to default
tk.MustExec("set @@session.tidb_opt_index_merge_cost_factor=1")
tk.MustExec("set @@session.tidb_opt_index_merge_cost_factor=default")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Pruning regression is not actually asserted in this test block

Line 648/Line 651 force INL_JOIN(i), so this validates hint precedence, not scan-ratio pruning. Also, Line 653 resets to default without asserting behavior after reset. Please add an unhinted join case that proves ratio-driven pruning changes plan selection.

Suggested test extension
 	// Test IndexJoin scan ratio threshold
 	tk.MustExec("drop table if exists t_outer, t_inner")
 	tk.MustExec("create table t_outer(a int primary key, b int, key(b))")
 	tk.MustExec("create table t_inner(a int primary key, b int, key(b))")
 	tk.MustExec("insert into t_outer values (1,1),(2,2),(3,3),(4,4),(5,5)")
 	tk.MustExec("insert into t_inner values (1,1),(2,2),(3,3),(4,4),(5,5)")
 	tk.MustExec("analyze table t_outer, t_inner")
 	tk.MustExec("set @@session.tidb_opt_hash_join_cost_factor=1")
 	tk.MustExec("set @@session.tidb_opt_merge_join_cost_factor=100")
 	tk.MustExec("set @@session.tidb_opt_index_join_cost_factor=1")
 	tk.MustExec("set @@session.tidb_opt_index_join_max_scan_rows_ratio=0")
 	rs = tk.MustQuery("explain format=verbose select /*+ INL_JOIN(i) */ * from t_outer o straight_join t_inner i on o.b = i.b").Rows()
 	require.Contains(t, rs[0][0].(string), "IndexJoin")
 	tk.MustExec("set @@session.tidb_opt_index_join_max_scan_rows_ratio=0.8")
 	rs = tk.MustQuery("explain format=verbose select /*+ INL_JOIN(i) */ * from t_outer o straight_join t_inner i on o.b = i.b").Rows()
 	require.Contains(t, rs[0][0].(string), "IndexJoin")
+
+	// Unhinted case should reflect ratio pruning.
+	unhinted := "explain format=verbose select * from t_outer o straight_join t_inner i on o.b = i.b"
+	tk.MustExec("set @@session.tidb_opt_index_join_max_scan_rows_ratio=0")
+	rs = tk.MustQuery(unhinted).Rows()
+	require.Contains(t, fmt.Sprint(rs), "IndexJoin")
+	tk.MustExec("set @@session.tidb_opt_index_join_max_scan_rows_ratio=default")
+	rs = tk.MustQuery(unhinted).Rows()
+	require.NotContains(t, fmt.Sprint(rs), "IndexJoin")
+
 	tk.MustExec("set @@session.tidb_opt_index_join_max_scan_rows_ratio=default")
 	tk.MustExec("set @@session.tidb_opt_hash_join_cost_factor=default")
 	tk.MustExec("set @@session.tidb_opt_merge_join_cost_factor=default")

As per coding guidelines MUST add a regression test and verify it fails before fix and passes after fix for bug fix changes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/planner/core/plan_cost_ver2_test.go` around lines 637 - 658, The current
block only validates hint precedence because the queries use the /*+ INL_JOIN(i)
*/ hint; add an unhinted join explain to prove ratio-driven pruning: run
tk.MustQuery("explain format=verbose select * from t_outer o straight_join
t_inner i on o.b = i.b") and capture rs, then assert plan selection changes
(e.g., require.NotContains(t, rs[0][0].(string), "IndexJoin") when
tk.MustExec("set @@session.tidb_opt_index_join_max_scan_rows_ratio=0") and
require.Contains(t, rs[0][0].(string), "IndexJoin") after tk.MustExec("set
@@session.tidb_opt_index_join_max_scan_rows_ratio=0.8"); finally after resetting
with tk.MustExec("set
@@session.tidb_opt_index_join_max_scan_rows_ratio=default") add an assertion
that the unhinted plan returns to the default expected choice to cover
regression.

Comment thread pkg/sessionctx/variable/sysvar.go
@codecov

codecov Bot commented May 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.59701% with 13 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (release-8.5-20251125-v8.5.4@2389a2f). Learn more about missing BASE report.

Additional details and impacted files
@@                       Coverage Diff                        @@
##             release-8.5-20251125-v8.5.4     #68557   +/-   ##
================================================================
  Coverage                               ?   57.2296%           
================================================================
  Files                                  ?       1784           
  Lines                                  ?     637096           
  Branches                               ?          0           
================================================================
  Hits                                   ?     364608           
  Misses                                 ?     247938           
  Partials                               ?      24550           
Flag Coverage Δ
integration 37.3155% <56.7164%> (?)
unit 72.6013% <80.5970%> (?)

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

Components Coverage Δ
dumpling 52.9278% <0.0000%> (?)
parser ∅ <0.0000%> (?)
br 52.9899% <0.0000%> (?)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Signed-off-by: guo-shaoge <shaoge1994@163.com>
@ti-chi-bot ti-chi-bot Bot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels May 21, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/planner/core/casetest/cbotest/cbo_test.go`:
- Around line 709-763: This change adds a new Go test function
TestAnalyzeSuiteRegression but did not include the Bazel metadata updates
required for new tests; run make bazel_prepare from the repo root to regenerate
BUILD.bazel / **/*.bazel / **/*.bzl and commit any produced metadata files (or
confirm and record that the command is a no-op for this package), ensuring the
Bazel outputs that reference the new test (TestAnalyzeSuiteRegression in
pkg/planner/core/casetest/cbotest/cbo_test.go and any symbols such as
GetAnalyzeSuiteData) are included in the PR.

In `@pkg/planner/core/casetest/testdata/json_plan_suite_out.json`:
- Around line 6-23: The test output file json_plan_suite_out.json has had its
case expectations replaced with empty "SQL" strings and null "JSONPlan" values
which breaks TestJSONPlanInExplain; restore each test case's original expected
SQL and JSONPlan entries (or re-run the recorder to re-record the suite) so the
JSON contains concrete SQL and non-null JSONPlan objects for each case, ensuring
TestJSONPlanInExplain can compare actual explain output against the recorded
"SQL" and "JSONPlan" values.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: b2c7b760-c574-407c-8820-958a4e7d959b

📥 Commits

Reviewing files that changed from the base of the PR and between a5615ab and 55a4b22.

📒 Files selected for processing (9)
  • pkg/executor/testdata/prepare_suite_out.json
  • pkg/planner/core/casetest/binaryplan/testdata/binary_plan_suite_out.json
  • pkg/planner/core/casetest/cbotest/cbo_test.go
  • pkg/planner/core/casetest/cbotest/testdata/analyze_suite_in.json
  • pkg/planner/core/casetest/cbotest/testdata/analyze_suite_out.json
  • pkg/planner/core/casetest/testdata/integration_suite_out.json
  • pkg/planner/core/casetest/testdata/json_plan_suite_out.json
  • pkg/planner/core/casetest/tpch/testdata/tpch_suite_out.json
  • tests/integrationtest/r/planner/core/plan_cost_ver2.result

Comment thread pkg/planner/core/casetest/cbotest/cbo_test.go
Comment thread pkg/planner/core/casetest/testdata/json_plan_suite_out.json Outdated
Signed-off-by: guo-shaoge <shaoge1994@163.com>
Signed-off-by: guo-shaoge <shaoge1994@163.com>
Signed-off-by: guo-shaoge <shaoge1994@163.com>
@ti-chi-bot ti-chi-bot Bot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels May 22, 2026
@guo-shaoge guo-shaoge changed the title planner/core: discourage degenerate index joins when probe rows approach a full scan planner/core: discourage degenerate index joins when probe rows approach a full scan | tidb-test=release-8.5-20251125-v8.5.4 May 22, 2026
Signed-off-by: guo-shaoge <shaoge1994@163.com>
@ti-chi-bot ti-chi-bot Bot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels May 22, 2026
Signed-off-by: guo-shaoge <shaoge1994@163.com>
…ithub.com:guo-shaoge/tidb into cp_v8.5.4-20260329_refine_cost_indexjoin_hashjoin
Signed-off-by: guo-shaoge <shaoge1994@163.com>
Signed-off-by: guo-shaoge <shaoge1994@163.com>
Signed-off-by: guo-shaoge <shaoge1994@163.com>
@guo-shaoge guo-shaoge changed the title planner/core: discourage degenerate index joins when probe rows approach a full scan | tidb-test=release-8.5-20251125-v8.5.4 planner/core: discourage degenerate index joins when probe rows approach a full scan | tidb-test=pr/2747 May 22, 2026
Signed-off-by: guo-shaoge <shaoge1994@163.com>
@guo-shaoge

Copy link
Copy Markdown
Contributor Author

/retest

Signed-off-by: guo-shaoge <shaoge1994@163.com>
tk.MustExec("create table t1(a int, c int, index idx(a))")
tk.MustExec("set tidb_mem_quota_query=10")
err := tk.ExecToErr("select /*+hash_join(t1)*/ t.a, t1.a from t use index(idx), t1 use index(idx) where t.a = t1.a")
err := tk.QueryToErr("select /*+hash_join(t1)*/ t.a, t1.a from t use index(idx), t1 use index(idx) where t.a = t1.a")

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ExecToErr only parse and compile SQL, result will not be fetched from resultSet.
The original code path will build IndexJoin first, and memory error occurs when building IndexJoin.
The new code path will build HashJoin first, and will skip build IndexJoin and return directly if there is a HashJoin hint. That's why we skipped build IndexJoin and memory error will not occurs when compile this SQL.
And we have to trigger the error using QueryToErr, which will fetch result from result set.

@ti-chi-bot ti-chi-bot Bot added the needs-1-more-lgtm Indicates a PR needs 1 more LGTM. label May 22, 2026
terry1purcell
terry1purcell previously approved these changes May 22, 2026
@ti-chi-bot ti-chi-bot Bot added lgtm and removed needs-1-more-lgtm Indicates a PR needs 1 more LGTM. labels May 22, 2026
@ti-chi-bot

ti-chi-bot Bot commented May 22, 2026

Copy link
Copy Markdown

[LGTM Timeline notifier]

Timeline:

  • 2026-05-22 10:07:03.45775437 +0000 UTC m=+1093.427919432: ☑️ agreed by qw4990.
  • 2026-05-22 14:02:32.968077048 +0000 UTC m=+15222.938242110: ☑️ agreed by terry1purcell.

Signed-off-by: guo-shaoge <shaoge1994@163.com>
…ithub.com:guo-shaoge/tidb into cp_v8.5.4-20260329_refine_cost_indexjoin_hashjoin
@guo-shaoge
guo-shaoge dismissed stale reviews from terry1purcell and qw4990 via fec26e7 May 22, 2026 14:17
Signed-off-by: guo-shaoge <shaoge1994@163.com>
Signed-off-by: guo-shaoge <shaoge1994@163.com>
Signed-off-by: guo-shaoge <shaoge1994@163.com>
qw4990
qw4990 previously approved these changes May 22, 2026
AilinKid
AilinKid previously approved these changes May 22, 2026
@guo-shaoge

Copy link
Copy Markdown
Contributor Author

/retest

Signed-off-by: guo-shaoge <shaoge1994@163.com>
@guo-shaoge
guo-shaoge dismissed stale reviews from AilinKid and qw4990 via 5a8e575 May 22, 2026 15:58
Signed-off-by: guo-shaoge <shaoge1994@163.com>
@ti-chi-bot

ti-chi-bot Bot commented May 22, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: 0xPoe, terry1purcell, yudongusa

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

The pull request process is described 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

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

Labels

approved lgtm release-note-none Denotes a PR that doesn't merit a release note. sig/planner SIG: Planner size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants