pingcap / pingcap/tidb

executor, session: extend point-get execution shortcut to non-prepared statements

Open
#70,000 1 comment 0 reactions 0 assignees View on GitHub
component/executor sig/execution type/enhancement
Dominant language
Go
Stars
40.5k
Forks
6.2k
PR merge metrics
PR metrics pending

Description

## Enhancement

Extend the point-get execution shortcut (currently used only by prepared statements) to non-prepared `PointGet` / `BatchPointGet` statements.

### Background

In `session.executeStmtImpl`, statements with `stmt.PsStmt != nil` (prepared statements resolved to a point plan) take a simplified execution path that skips the full `runStmt` envelope — rich trace events, flight recorder triggers, and telemetry counters. Non-prepared point-get queries, even when `TryFastPlan` or the non-prepared plan cache has already produced a `*PointGetPlan` / `*BatchPointGetPlan`, still pay the full `runStmt` overhead on every execution.

For high-QPS point-lookup workloads issued as plain text queries (very common with ORMs and simple applications that do not use prepared statements), this per-statement envelope is measurable overhead that the prepared path already avoids.

### Proposal

When the statement's plan is already a `*PointGetPlan` or `*BatchPointGetPlan`, route it through the same execution shortcut used by prepared point-gets. The change is gated behind a new session/global variable `tidb_enable_point_get_exec_shortcut` (default `OFF`) so the behavior can soak before being considered for default-on.

Supporting changes:
- `ExecStmt.PointGet` handles `a.PsStmt == nil`: the prepared-statement executor cache is simply skipped for non-prepared statements, which build a fresh executor each time.
- The shortcut sits after optimization, so it is orthogonal to (and composes with) the non-prepared plan cache.

### Benchmark results

A/B benchmark (`BenchmarkPointGetExecShortcut` in `pkg/planner/core/tests/pointget`) comparing the same non-prepared query with the shortcut off vs. on, mock store, Apple M-series (darwin/arm64), `-benchtime=2s -count=3`:

| Case | Shortcut OFF (ns/op) | Shortcut ON (ns/op) | Improvement |
| --- | --- | --- | --- |
| PointGet | 49363 / 50167 / 51693 | 45072 / 44417 / 44950 | ~10–11% |
| BatchPointGet | 59382 / 64640 / 59104 | 52925 / 52027 / 52488 | ~11–12% |

The ranges do not overlap across runs. On a real cluster the absolute KV latency is larger, but the saved per-statement CPU overhead is the same, so this directly improves point-lookup throughput per core.

### Trade-offs

The shortcut path emits a simplified `stmt.start` trace event and skips some observability work done by the full `runStmt` path (rich trace events, flight recorder triggers, telemetry counters) — the same trade-off prepared point-gets already make today. Defaulting the variable to `OFF` keeps existing behavior unchanged until the observability gap is reviewed.

### Verification

- `go test -run '^$' -bench BenchmarkPointGetExecShortcut -benchtime=2s -count=3 -tags=intest,deadlock` in `pkg/planner/core/tests/pointget` (results above).
- `./tools/check/failpoint-go-test.sh pkg/sessiontxn -run TestNonPreparedPointGetExecShortcut -count=1` — passes; covers correctness of the shortcut path for non-prepared point-get and batch point-get, including txn-context behavior.

Contributor guide

Open the contributing guide

Research direction

Start with session.executeStmtImpl and ExecStmt.PointGet, then inspect the existing prepared point-get shortcut and the session/global variable handling. Run BenchmarkPointGetExecShortcut in pkg/planner/core/tests/pointget and TestNonPreparedPointGetExecShortcut through the listed commands; done means both non-prepared point-get forms use the gated shortcut correctly with transaction context preserved.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
backend, databases
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.