perf(log): optimize PG log store queries and expired partition cleanup

- Count/节点访问日志统计改为单次扫描聚合,WAF 按 IP 聚合由三次扫描合并为两次
- IPSummaries 归属地改为取过滤窗口内最新记录(对齐 ClickHouse argMax 口径),
  子查询带窗口条件,可分区裁剪并命中索引
- 新增 goose 迁移:of_node_access_logs (logged_at DESC, id DESC) 前导索引与
  lower(trim(host)) 表达式索引,加速列表排序与主机过滤
- 过期日志清理先按数据校验直接 DROP 完全过期整月分区,再对边界月逐行删除;
  启动时兜底预建当月及未来 2 个月分区,跨月停机重启后首次写入不再报
  "no partition of relation found"
This commit is contained in:
ryan
2026-08-09 10:20:58 +08:00
parent 08d28c2c8e
commit f530cd4025
12 changed files with 519 additions and 84 deletions
+6
View File
@@ -107,6 +107,12 @@ func CleanupExpired(ctx context.Context) (*CleanupSummary, error) {
return nil, fmt.Errorf("ensure partitions: %w", err)
}
// 先直接删除完全过期的整月分区(比逐行 DELETE 快几个数量级、无 MVCC/WAL 负担),
// 再对边界月份执行 DeleteBefore(边界月仍可能含未过期数据,不可整表删)。
if err := s.AccessLogs.DropExpiredPartitions(ctx, cutoff); err != nil {
return nil, fmt.Errorf("drop expired partitions: %w", err)
}
if err := cleanupTable("node_access_logs", func() (int64, error) {
return s.AccessLogs.DeleteBefore(ctx, cutoff)
}, summary); err != nil {