Skip to content

perf(analytics): cut git observation view query memory - #1733

Merged
aleksdotbar merged 4 commits into
mainfrom
perf/git-observations-view-memory
Jul 10, 2026
Merged

perf(analytics): cut git observation view query memory#1733
aleksdotbar merged 4 commits into
mainfrom
perf/git-observations-view-memory

Conversation

@aleksdotbar

@aleksdotbar aleksdotbar commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

The git_metric_observations view runs live on every metric query, and its measure branches execute as concurrent pipelines — so peak memory is per-branch, not per-query. Its FINAL reads and cross-table joins pushed the shared ClickHouse memory tracker over its ceiling under load, aborting queries.

View

  • Pre-aggregate file changes to commit × category grain before the authorship join. Per-file rows and file-path strings leave the pipeline at aggregation, so they never enter a join side or a measure aggregation.
  • Drop FINAL from the two reads whose uniqExact vote duplicate row versions cannot inflate. FINAL stays on the commit and pull-request reads, where it is the cheapest correct dedup.
  • Result parity verified; dedup semantics unchanged.

Query bounds

  • Cap max_threads and set a per-query max_memory_usage in the ClickHouse client config, alongside the existing execution timeout. One enforcement point covers metric queries, validator probes, and the legacy query endpoints.
  • A pathological query now fails alone with a typed error instead of exhausting the shared server tracker and killing every in-flight query on the instance.

Refs #1706.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added configurable per-query limits for processing threads and memory usage.
    • Analytics queries now use defined resource limits for more predictable execution.
  • Bug Fixes

    • Improved file-change categorization and aggregation in analytics metrics.
    • Refined pull request author attribution to avoid duplicate records affecting results.
  • Performance

    • Optimized metric query processing to reduce unnecessary memory usage and improve reliability.

aleksdotbar and others added 2 commits July 10, 2026 12:20
The git_metric_observations view runs live on every metric query and its measure branches execute concurrently, so peak memory is per-branch. Pre-aggregate file changes to commit x category grain before the authorship join, so per-file rows and path strings never enter a join side or a measure aggregation. Drop FINAL from the two reads whose uniqExact vote cannot be inflated by duplicate row versions; keep it on the commit and pull-request reads where it is the cheapest correct dedup.

Result parity verified; dedup semantics unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Aleksandr Barkhatov <pm@aleks.bar>
Observation views execute live with parallel union branches, so per-query memory scales with thread count. Cap max_threads and set a per-query max_memory_usage in the ClickHouse client config, alongside the existing execution timeout, so one heavy query fails alone with a typed error instead of pushing the shared server memory tracker over its limit and aborting every in-flight query on the instance.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Aleksandr Barkhatov <pm@aleks.bar>
@aleksdotbar
aleksdotbar requested a review from a team as a code owner July 10, 2026 10:21
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@aleksdotbar, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 32 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 497fd2d4-b182-46db-93a1-db8da0694cf9

📥 Commits

Reviewing files that changed from the base of the PR and between fee739a and 8d93137.

📒 Files selected for processing (1)
  • src/backend/services/analytics/src/domain/metric_results/compiler.rs
📝 Walkthrough

Walkthrough

ClickHouse clients now support per-query thread and memory limits, with analytics applying explicit bounds. The Git metrics view also changes file-change aggregation and removes unnecessary deduplication qualifiers from author-email election.

Changes

ClickHouse query resource limits

Layer / File(s) Summary
Configure and apply query limits
src/backend/libs/insight-clickhouse/src/config.rs, src/backend/libs/insight-clickhouse/src/lib.rs, src/backend/services/analytics/src/gear.rs
Config exposes optional thread and memory limits, Client::query applies them to ClickHouse settings, tests cover the new branches, and analytics configures explicit values.

Git metrics query optimization

Layer / File(s) Summary
Refine Git metrics aggregation
src/ingestion/gold/git_metric_observations.sql
File changes are pre-aggregated by commit and category, category labels use the grouped category, and unnecessary FINAL qualifiers are removed from author-email election joins.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant AnalyticsApiGear
  participant ClickHouseConfig
  participant ClickHouseClient
  participant QueryHandle
  AnalyticsApiGear->>ClickHouseConfig: configure thread and memory limits
  ClickHouseConfig->>ClickHouseClient: create client
  ClickHouseClient->>QueryHandle: apply max_threads and max_memory_usage
Loading

Suggested reviewers: ktursunov

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: reducing memory use for the git observation view query.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/git-observations-view-memory

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/ingestion/gold/git_metric_observations.sql`:
- Around line 44-55: Clarify the memory-shape comment so only the two
pr_commit_emails reads are described as avoiding FINAL; explicitly state that
file_changes retains FINAL for deduplication, while pre-aggregation only reduces
join and aggregation memory. Update the comment near the references to FINAL,
pr_commit_emails, and file_changes without changing query behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d1e1b56f-df05-4647-81dd-ffef7fe052d3

📥 Commits

Reviewing files that changed from the base of the PR and between 28495ab and fee739a.

📒 Files selected for processing (4)
  • src/backend/libs/insight-clickhouse/src/config.rs
  • src/backend/libs/insight-clickhouse/src/lib.rs
  • src/backend/services/analytics/src/gear.rs
  • src/ingestion/gold/git_metric_observations.sql

Comment on lines +44 to +55
--
-- Memory shape (this view executes live on every metric query, and its
-- measure branches run concurrently within one query, so per-branch memory
-- multiplies): FINAL is the cheapest dedup here — a streaming merge of
-- sorted parts — and stays wherever dedup is needed. Version-ordered
-- `ORDER BY .. LIMIT 1 BY` is not an alternative: it buffers a full sort
-- of the read (measured ~2x the memory of FINAL at scale). The two reads
-- that avoid FINAL do so because they need no dedup at all: the identity
-- vote in pr_commit_emails aggregates by uniqExact, which duplicate row
-- versions cannot inflate. file_changes pre-aggregates to commit x category
-- grain before joining, so per-file rows and file_path strings never enter
-- a join side or a measure aggregation.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Clarify that file_changes still uses FINAL; the current wording reads as if it avoids it.

The block introduces "the two reads that avoid FINAL" and then, under the same justification, describes file_changes pre-aggregation. But line 116 retains FINAL on class_git_file_changes, and correctly so: sum(lines_added) over grouped rows is not dedup-safe — stale ReplacingMergeTree versions would inflate the sum. Grouping to commit×category grain reduces join/aggregation memory but does not remove the need for dedup.

The only reads that actually drop FINAL are the two in pr_commit_emails. Recommend tightening the wording so a future reader does not mistakenly remove FINAL at line 116.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/ingestion/gold/git_metric_observations.sql` around lines 44 - 55, Clarify
the memory-shape comment so only the two pr_commit_emails reads are described as
avoiding FINAL; explicitly state that file_changes retains FINAL for
deduplication, while pre-aggregation only reduces join and aggregation memory.
Update the comment near the references to FINAL, pr_commit_emails, and
file_changes without changing query behavior.

aleksdotbar and others added 2 commits July 10, 2026 12:46
Cheaper equivalents for three compiled query patterns, results unchanged:

- Peer view computes all three quartiles from one quantilesExactIf per metric (a single sort) instead of three separate quantileExactIf calls; min/max come back already-Nullable from *IfOrNull, dropping a redundant toNullable.
- Dimension extraction locates the tuple once with indexOf on the key column and reuses the index, replacing three arrayFilter passes over the tuple array per row.
- Histogram derives each entity's value bounds with a window pass over the events, replacing the bounds self-join and its second scan of the observation view.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Aleksandr Barkhatov <pm@aleks.bar>
@aleksdotbar
aleksdotbar enabled auto-merge July 10, 2026 10:50
.with_query_max_threads(4)
.with_query_max_memory_bytes(1_610_612_736),
);
let _q = client.query("SELECT 1");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assert missing in this test.

@aleksdotbar
aleksdotbar merged commit 4c5f307 into main Jul 10, 2026
40 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants