Add default analyze_interval for partitioned tables

What & why

Partitioning strategies defaulted analyze_interval to nil, so the post-rotation ANALYZE in PartitionManager#run_analyze_on_partitioned_table never fired for any partitioned table that did not explicitly opt in. Only Ci::Partitionable set it (3.days).

Root-cause class: nil default → newly-rotated partitions never get an ANALYZE on rotation → they run with no/stale planner statistics until autovacuum eventually catches up → stale-stats bad query plans. This was a contributing factor in INC-13566 (the security_findings-specific fix is #624174 / !252297).

Change

Introduces a shared Gitlab::Database::Partitioning::BaseStrategy::DEFAULT_ANALYZE_INTERVAL = 1.week and uses it as the default analyze_interval: on all three strategy families:

  • SlidingListStrategy (and CiSlidingListStrategy)
  • IntRangeStrategy
  • Time::BaseStrategy (monthly / weekly / daily)

Any partitioned table lacking an explicit value now gets periodic post-rotation stats. Per-model overrides still winCi::Partitionable stays 3.days, and Security::Finding will be 1.day via #624174.

Ops kill-switch

Because this flips ~50 previously-never-analyzed partitioned tables to a periodic ANALYZE at once, it ships with an ops feature flag analyze_partitioned_tables_on_rotation (default enabled). If the recurring ANALYZE ever causes unexpected database load, disabling the flag immediately stops all post-rotation ANALYZE (a single global off-switch), reverting to prior behaviour without a revert/deploy. Gated in run_analyze_on_partitioned_table.

Why 1.week (conservative)

The post-rotation ANALYZE is issued against the parent table, and ANALYZE on a partitioned parent recurses through the entire partition hierarchy, not just the newly-created leaf. For very large tables (e.g. security_findings, hundreds of millions of rows across many partitions) a full-hierarchy ANALYZE is non-trivial recurring load. A weekly cadence bounds that cost while still ensuring rotated partitions get stats. It is throttled per-interval by last_analyzed_at_within_interval?, so each table analyzes at most once per week by default.

Feature flag history

The original feature flag database_analyze_on_partitioned_tables (introduced with the feature in !130599 (merged), #423135 (closed)) was removed in !132219 (merged) (16.x). The post-rotation ANALYZE path is therefore always-on / no longer gated, which is precisely why this MR reintroduces a dedicated ops kill-switch for it.

Follow-up

Make the post-rotation ANALYZE target only the newly-created leaf partition rather than the parent. That removes the full-hierarchy cost concern and would allow a tighter default interval. Tracked as a follow-up to this MR.

Tests

  • DEFAULT_ANALYZE_INTERVAL fallback expectations on the sliding-list, ci-sliding-list, int-range, monthly and weekly strategy specs.
  • partition_manager_spec / partitioning_spec "when analyze_interval is not set" cases now assert the default runs a throttled ANALYZE, plus a new context asserting the ops flag disabled stops the ANALYZE entirely.
  • Verified locally: partition_manager_spec + partitioning_spec → 65 examples, 0 failures (2 pending are unrelated single-DB skips). Rubocop clean.

Closes #624175. Complements #624174.

Edited by Gregory Havenga

Merge request reports

Loading
Loading