-
Notifications
You must be signed in to change notification settings - Fork 5.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
parser, planner: add query block level no_decorrelate
hint
#37633
parser, planner: add query block level no_decorrelate
hint
#37633
Conversation
[REVIEW NOTIFICATION] This pull request has been approved by:
To complete the pull request process, please ask the reviewers in the list to review by filling The full list of commands accepted by this bot can be found here. Reviewer can indicate their review by submitting an approval review. |
|
||
"SELECT ta.NAME FROM ta WHERE EXISTS (select 1 from tb where ta.code = tb.code and tb.NAME LIKE 'chad9%') AND (select max(id) from tc where ta.name=tc.name and tc.name like 'chad99%') > 100 and (select max(id) from td where ta.id=td.id and td.name like 'chad999%') > 100", | ||
"SELECT ta.NAME FROM ta WHERE EXISTS (select /*+ semi_join_rewrite() */ 1 from tb where ta.code = tb.code and tb.NAME LIKE 'chad9%') AND (select /*+ no_decorrelate() */ max(id) from tc where ta.name=tc.name and tc.name like 'chad99%') > 100 and (select /*+ no_decorrelate() */ max(id) from td where ta.id=td.id and td.name like 'chad999%') > 100", | ||
"SELECT ta.NAME FROM ta WHERE EXISTS (select /*+ no_decorrelate() */ 1 from tb where ta.code = tb.code and tb.NAME LIKE 'chad9%') AND (select /*+ no_decorrelate() */ max(id) from tc where ta.name=tc.name and tc.name like 'chad99%') > 100 and (select /*+ no_decorrelate() */ max(id) from td where ta.id=td.id and td.name like 'chad999%') > 100" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add some test cases about USE_TOJA
hint.
Besides, please use these hint in the same query block to see what happened if these hint are conflicts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add these test cases about the TiFlash and partition tables(Both static and dynamic mode)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently, USE_TOJA
and NO_DECORRELATE
won't interfere with each other. USE_TOJA
handles non-correlated IN
subquery, and NO_DECORRELATE
handles correlated subquery.
And USE_TOJA
is a query level hint instead of a query block level one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I personally think we don't need to add such cases.
Because decorrelation-related logic happens very early in the whole optimization process, it's before any partition-related rewrites and any physical operator.
I think they won't interfere with each other. If tiflash and partitioned table related logic work well with Apply
, there should be no other issues.
@@ -318,7 +318,7 @@ func (er *expressionRewriter) constructBinaryOpFunction(l expression.Expression, | |||
|
|||
// buildSubquery translates the subquery ast to plan. | |||
// Currently, only the EXIST can apply the rewrite hint(rewrite the semi join to inner join with aggregation). | |||
func (er *expressionRewriter) buildSubquery(ctx context.Context, subq *ast.SubqueryExpr, rewriteHintCanTakeEffect bool) (np LogicalPlan, hasSemiJoinRewriteHint bool, err error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please update the comments for this function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated.
oldSubQCtx := er.b.subQueryCtx | ||
er.b.subQueryCtx = subqueryCtx | ||
oldHintFlags := er.b.subQueryHintFlags | ||
er.b.subQueryHintFlags = 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the meaning for this part?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As L331 said, first, we save the current values of subQueryCtx
and subQueryHintFlags
, then set them to values we want to pass to the subquery, after we're done in this function, we restore the values to the saved values.
b.subQueryHintFlags |= HintFlagSemiJoinRewrite | ||
case HintNoDecorrelate: | ||
if b.subQueryCtx == notHandlingSubquery { | ||
b.ctx.GetSessionVars().StmtCtx.AppendWarning(ErrInternal.GenWithStack("NO_DECORRELATE() is inapplicable because it's not in an IN subquery, an EXISTS subquery, an ANY/ALL/SOME subquery or a scalar subquery.")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should continue
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated.
It actually doesn't matter, I added it to be consistent with the code above.
planner/core/expression_rewriter.go
Outdated
} | ||
// Pop the handle map generated by the subquery. | ||
er.b.handleHelper.popMap() | ||
return np, er.b.hasValidSemiJoinHint, nil | ||
return np, er.b.subQueryHintFlags, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems we always return 0
for the return value hintFlags uint64
? Because we set er.b.subQueryHintFlags = 0
in line335 and return always execute before the defer function in line337-341.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. You can see the two examples to see golang's behavior:
https://go.dev/play/p/jg7rfs2Qc6f
https://go.dev/play/p/Cb7L2I03tvC
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's indeed a bit confusing, I updated the code to make it more clear.
/merge |
This pull request has been accepted and is ready to merge. Commit hash: b8d980d
|
/hold |
As discussed before, let's merge this PR after release-6.3 branching. |
/unhold |
TiDB MergeCI notify✅ Well Done! New fixed [1] after this pr merged.
|
What problem does this PR solve?
Issue Number: close #37789
What is changed and how it works?
Implement query block level
no_decorrelate()
hint.Check List
Tests
Side effects
Documentation
Release note
Please refer to Release Notes Language Style Guide to write a quality release note.