Skip to content

Conversation

@ChaitanyaD48
Copy link
Contributor

Description

This PR enhances the pushDerived function in route_planning.go to consider all single-shard routing scenarios, not just those using the engine.EqualUnique opcode.

IsSingleShard() method checks if a route is a single shard route by looking at its opcode. The method returns true for the following opcodes: Unsharded, DBA, Next, EqualUnique, and Reference.

Reference - vitess/go/vt/vtgate/engine/routing.go

func (code Opcode) IsSingleShard() bool {
	switch code {
	case Unsharded, DBA, Next, EqualUnique, Reference:
		return true
	}
	return false
}

Related Issue(s)

Fixes #18952

Checklist

  • "Backport to:" labels have been added if this change should be back-ported to release branches
  • If this change is to be back-ported to previous releases, a justification is included in the PR description
  • Tests were added or are not required
  • Did the new or modified tests pass consistently locally and on CI?
  • Documentation was added or is not required

Deployment Notes

AI Disclosure

Signed-off-by: ChaitanyaD48 <chaitanya.d48@gmail.com>
@vitess-bot
Copy link
Contributor

vitess-bot bot commented Dec 2, 2025

Review Checklist

Hello reviewers! 👋 Please follow this checklist when reviewing this Pull Request.

General

  • Ensure that the Pull Request has a descriptive title.
  • Ensure there is a link to an issue (except for internal cleanup and flaky test fixes), new features should have an RFC that documents use cases and test cases.

Tests

  • Bug fixes should have at least one unit or end-to-end test, enhancement and new features should have a sufficient number of tests.

Documentation

  • Apply the release notes (needs details) label if users need to know about this change.
  • New features should be documented.
  • There should be some code comments as to why things are implemented the way they are.
  • There should be a comment at the top of each new or modified test to explain what the test does.

New flags

  • Is this flag really necessary?
  • Flag names must be clear and intuitive, use dashes (-), and have a clear help text.

If a workflow is added or modified:

  • Each item in Jobs should be named in order to mark it as required.
  • If the workflow needs to be marked as required, the maintainer team must be notified.

Backward compatibility

  • Protobuf changes should be wire-compatible.
  • Changes to _vt tables and RPCs need to be backward compatible.
  • RPC changes should be compatible with vitess-operator
  • If a flag is removed, then it should also be removed from vitess-operator and arewefastyet, if used there.
  • vtctl command output order should be stable and awk-able.

@vitess-bot vitess-bot bot added NeedsBackportReason If backport labels have been applied to a PR, a justification is required NeedsDescriptionUpdate The description is not clear or comprehensive enough, and needs work NeedsIssue A linked issue is missing for this Pull Request NeedsWebsiteDocsUpdate What it says labels Dec 2, 2025
@github-actions github-actions bot added this to the v24.0.0 milestone Dec 2, 2025
@arthurschreiber
Copy link
Member

Can you also add test cases that show the impact of this change?

@ChaitanyaD48
Copy link
Contributor Author

Can you also add test cases that show the impact of this change?

Hi @arthurschreiber
I’ve been testing a few scenarios to validate the impact of this change, and I think this testcase demonstrates the expected behavior -

[
  {
    "comment": "Derived table pushdown optimization",
    "query": "SELECT * FROM (SELECT DISTINCT id, col FROM user.ref WHERE id = 1 LIMIT 10) as sub",
    "plan": {
      "Type": "Passthrough",
      "QueryType": "SELECT",
      "Original": "SELECT * FROM (SELECT DISTINCT id, col FROM user.ref WHERE id = 1 LIMIT 10) as sub",
      "Instructions": {
        "OperatorType": "Route",
        "Variant": "Reference",
        "Keyspace": {
          "Name": "user",
          "Sharded": true
        },
        "FieldQuery": "select id, col from (select id, col from ref where 1 != 1) as sub where 1 != 1",
        "Query": "select id, col from (select distinct id, col from ref where id = 1 limit 10) as sub"
      },
      "TablesUsed": [
        "user.ref"
      ]
    }
  }
]

Properties of the query -

  • user.ref is a Reference table (replicated across shards)
  • Subquery contains LIMIT, making the operator non-mergeable thus !op.IsMergeable(ctx) condition becomes true.
  • Routing opcode is Reference, which is now recognized as single-shard thus !innerRoute.Routing.OpCode().IsSingleShard() condition becomes false

These are the test results in both scenarios

Previous Case (EqualUnique-only):

  • isMergeable = false
  • opcode = Reference
  • Pushdown is blocked, even though the route is actually single-shard
  • vtgate must perform DISTINCT + LIMIT

Output -
image

Refactored Case (using IsSharded):

  • IsSingleShard() = true for Reference variant
  • Pushdown is allowed
  • MySQL executes the entire subquery

Output -
image

What do you think?

@ChaitanyaD48
Copy link
Contributor Author

Hi @arthurschreiber just following up on my previous comment.
Let me know what do you think of the test case provided.
Thanks!

@arthurschreiber
Copy link
Member

@ChaitanyaD48 The test case makes sense to me. 👍

…erived-use-isSingleShard

Signed-off-by: ChaitanyaD48 <chaitanya.d48@gmail.com>
Signed-off-by: ChaitanyaD48 <chaitanya.d48@gmail.com>
@ChaitanyaD48
Copy link
Contributor Author

ChaitanyaD48 commented Dec 18, 2025

Thanks! @arthurschreiber
I've added the test case to reference_cases.json

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

Labels

NeedsBackportReason If backport labels have been applied to a PR, a justification is required NeedsDescriptionUpdate The description is not clear or comprehensive enough, and needs work NeedsIssue A linked issue is missing for this Pull Request NeedsWebsiteDocsUpdate What it says

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Performance: pushDerived should use IsSingleShard() check

2 participants