statistics: partition-level analyze options depend on tidb_partition_prune_mode
- Dominant language
- Go
- Stars
- 40.5k
- Forks
- 6.2k
- PR merge metrics
- PR metrics pending
Description
## Enhancement
Partition-level analyze options behave differently depending on `tidb_partition_prune_mode`, even though that variable is settable per session and globally and is unrelated to the statement being run.
In `genV2AnalyzeOptions` (`pkg/planner/core/planbuilder.go`), a partition-targeted analyze in dynamic mode discards the statement's options and column choice entirely:
```go
if !isAnalyzeTable && dynamicPrune && (len(astOpts) > 0 || astColChoice != ast.DefaultChoice) {
astOpts = make(map[ast.AnalyzeOptionType]*uint64, 0)
astColChoice = ast.DefaultChoice
astColList = make([]*model.ColumnInfo, 0)
b.ctx.GetSessionVars().StmtCtx.AppendWarning(errors.NewNoStackError("Ignore columns and options when analyze partition in dynamic mode"))
}
```
In static mode the same statement is honoured and persisted per partition. `saveAnalyzeOptions` (`pkg/executor/analyze.go`) mirrors this by skipping partition rows in dynamic mode.
Two consequences:
1. The same `ANALYZE TABLE t PARTITION p0 WITH ...` means two different things depending on a session variable, and options persisted in `mysql.analyze_options` under one mode are silently ignored under the other.
2. `ANALYZE TABLE t PARTITION p0 WITH DEFAULT ` (added for #69853) inherits the asymmetry. A reset targets persisted state rather than the current run, so arguably it should take effect regardless of the prune mode in force when it happens to be issued.
### Proposal
Two directions, listed separately because they can be decided independently:
**a) Make the `DEFAULT` reset mode-independent.** Clearing a persisted partition option is a metadata operation on `mysql.analyze_options`. Ignoring it because of the current prune mode leaves the user unable to clear a value that a static-mode session persisted earlier.
**b) Support per-partition options in dynamic mode generally.** Dynamic mode still analyzes each partition and merges the results into global stats, so per-partition sampling is meaningful: a user who knows some partitions are more representative could sample those more heavily and the others less.
`SAMPLES` and `SAMPLERATE` are the coherent cases for (b). `BUCKETS` and `TOPN` are murkier, because the global merge re-buckets histograms and merges TopN across partitions, so uneven per-partition settings would give the merge uneven input. It may be right to allow the sampling options only.
### Notes
Static prune mode is deprecated. If it is eventually removed, the entire partition-level analyze options feature disappears with it, since dynamic mode discards those options today. That is an additional argument for deciding (b) rather than letting the behavior lapse by attrition.
Found while reviewing the `ANALYZE ... WITH DEFAULT` implementation for #69853.
Contributor guide
Research direction
Start in pkg/planner/core/planbuilder.go at genV2AnalyzeOptions and pkg/executor/analyze.go at saveAnalyzeOptions. Trace how partition options, DEFAULT resets, and mysql.analyze_options persistence behave in static and dynamic tidb_partition_prune_mode. First resolve whether the intended scope is mode-independent resets, sampling options in dynamic mode, or both; done means the chosen behavior is specified and covered across both modes.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- databases
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100