Set analyze_interval on Security::Finding partitions
What does this MR do?
Sets analyze_interval: 1.day on Security::Finding's partitioned_by declaration so newly-rotated security_findings partitions get planner statistics promptly.
Why
Corrective action for INC-13566 (#624174). New security_findings leaf partitions were left with no planner stats (reltuples = -1) because the partition manager's post-rotation ANALYZE is gated on analyze_interval, which Security::Finding never set. With no stats, the planner picked a 483M-row parallel sequential scan, saturating patroni-sec.
On the 1.day interval
Summary: 1.day is a deliberate tighter override than CI's 3.days and the 1.week framework default (!252300). It is not a daily unconditional ANALYZE, it is cheap, and it caps the "new partition with no stats" danger window at ~24h instead of up to a week. Details below.
Full reasoning (cost, throttle, interval choice)
-
Fires when no manual ANALYZE ran in the interval.
run_analyze_on_partitioned_tableonly fires whenlast_analyzed_at_within_interval?is false. That check readspg_stat_get_last_analyze_time, which reflects manual ANALYZE only (last_analyze), not autovacuum's auto-analyze (last_autoanalyze). So a healthy autovacuum does not satisfy this throttle: the manual ANALYZE fires whenever nothing manual ran in the last 24h, independent of autovacuum. This is still bounded and cheap (see next point), but it is not skipped just because autovacuum is caught up. -
ANALYZE is a bounded sample, not a scan. It samples ~
300 × default_statistics_targetrows regardless of the hundreds of millions of rows in a partition.security_findingsis a bounded rolling window (retention viastale_after+ partition detach), not an ever-growing table, so the parent-recurse ANALYZE covers a bounded set of partitions. Cheap relative to the unplanned seq scan it prevents. -
1.daycaps the danger window. The risky moment is a freshly-rotated leaf with zero stats. Partitions rotate roughly every 1-2 weeks (100GB fill orstale_after), faster under volume spikes.1.daybounds "cold partition, no stats" to ~24h; the1.weekdefault would let a new leaf sit statless for up to a week, which is the exact INC-13566 exposure window. -
Caveat (post-rotation gap). The throttle reads
last_analyze_timefrom the oldest partition as the table proxy, so a freshly-rotated leaf can still sit statless for up to the interval before the throttled parent-recurse ANALYZE next fires.1.dayshrinks that window rather than closing it; closing it properly (ANALYZE the just-created partition directly, bypassing the throttle) is tracked as a systemic follow-up in #624175.
The post-rotation ANALYZE runs ANALYZE (SKIP_LOCKED) on the parent (recurses all partitions), throttled to at most once per interval, with a 1h statement timeout.
Changes
ee/app/models/security/finding.rb: addanalyze_interval: 1.daytopartitioned_by.ee/spec/models/security/finding_spec.rb: assertpartitioning_strategy.analyze_interval == 1.day.