P95 Query Time

P95 Query Time

The 95th percentile database query duration — 95% of queries complete faster than this. Weighted by execution frequency across all queries. Slow queries are often caused by missing indexes or N+1 patterns.

34 ms

3.5%

Compared to previous 7 days

Execution Rate

Query Execution Rate

Total database queries executed over the last 14 days, expressed as an average rate. Spikes may indicate N+1 queries or inefficient data access patterns.

2.58 / hour

0.5%

Compared to previous 7 days

Query Responses

Query Responses

This panel shows all executions of this query, including performance metrics, duration distribution, and query execution details.

Click marker to copy SHA
Time Period Executions Avg Duration Min Duration ▲ Max Duration
Sep 9, 2026 53 19.64 ms 1.0 ms 50.0 ms
Sep 10, 2026 60 20.02 ms 1.0 ms 35.0 ms
Sep 11, 2026 61 16.56 ms 1.0 ms 49.0 ms
Sep 12, 2026 78 19.45 ms 1.0 ms 47.0 ms
Sep 13, 2026 50 15.76 ms 1.0 ms 35.0 ms
Sep 14, 2026 58 20.47 ms 1.0 ms 41.0 ms
Sep 16, 2026 63 16.02 ms 1.0 ms 35.0 ms
Sep 17, 2026 48 14.15 ms 1.0 ms 35.0 ms
Sep 18, 2026 63 18.1 ms 1.0 ms 34.0 ms
Sep 19, 2026 58 16.71 ms 1.0 ms 33.0 ms
Total of 15 record(s).

Normalized Query

SELECT * FROM (SELECT users.id, users.name, users.email, COUNT(posts.id) as post_count FROM users LEFT JOIN posts ON users.id = posts.user_id WHERE users.active = ? GROUP BY users.id) as user_posts JOIN (SELECT user_id, COUNT(*) as comment_count FROM comments WHERE approved = ? GROUP BY user_id) as user_comments ON user_posts.id = user_comments.user_id WHERE user_posts.post_count > ? AND user_comments.comment_count > ?

Diagnostics

Query Diagnostics

Automatically generated analysis for this query. Includes N+1 detection (from live request data), query characteristics, detected issues, optimization suggestions, and a database EXPLAIN plan. Click Re-analyze to regenerate.


Query Characteristics
Query Type
SELECT
Tables
3
Joins
2
Complexity Score
23
Has LIMIT
No
Has ORDER BY
No
Has GROUP BY
Yes
Has Subqueries
Yes

Issues Detected
  • Using SELECT * may retrieve unnecessary columns

Optimization Suggestions
  • Use includes() or preload() to load associated records — Eliminate N+1 queries and reduce database load
  • Use includes() to eager load associations — Eliminate N+1 queries and reduce database load
  • Use joins() when you only need to filter, not access associated data — Eliminate N+1 queries and reduce database load
  • Use preload() when you don't need to query on associations — Eliminate N+1 queries and reduce database load
  • Add single_column index: add_index :posts, :user_id — Fast JOIN execution
    add_index :posts, :user_id
  • Add single_column index: add_index :users, :active — Fast lookups for active = value queries
    add_index :users, :active

Query Locations

Query Locations

Shows where in your codebase this query originates, based on the last 30 days of executions. P95 duration and row count highlight the worst-case performance at each call site.

Location P95 Duration (ms) P95 Row Count Count
app/models/application_record.rb:12 34.0 494
app/jobs/notification_job.rb:39 31.0 1
app/jobs/cache_warming_job.rb:73 3.0 1
app/jobs/analytics_job.rb:101 28.0 1
app/jobs/data_export_job.rb:66 8.0 1
app/jobs/cleanup_job.rb:32 39.0 1
app/jobs/image_processing_job.rb:114 21.0 1

Raw Data

{
  "query": {
    "id": 86,
    "normalized_sql": "SELECT * FROM (SELECT users.id, users.name, users.email, COUNT(posts.id) as post_count FROM users LEFT JOIN posts ON users.id = posts.user_id WHERE users.active = ? GROUP BY users.id) as user_posts JOIN (SELECT user_id, COUNT(*) as comment_count FROM comments WHERE approved = ? GROUP BY user_id) as user_comments ON user_posts.id = user_comments.user_id WHERE user_posts.post_count > ? AND user_comments.comment_count > ?",
    "analyzed_at": "2026-09-23 06:02:25 UTC"
  },
  "performance": {
    "total_executions": 500,
    "p95_duration_ms": "34.0",
    "avg_duration_ms": 17.42,
    "p95_row_count": null,
    "avg_row_count": null
  },
  "characteristics": {
    "query_type": "SELECT",
    "table_count": 3,
    "join_count": 2,
    "where_clause_complexity": 1,
    "has_subqueries": true,
    "has_limit": false,
    "has_order_by": false,
    "has_group_by": true,
    "has_having": false,
    "has_distinct": false,
    "has_aggregations": true,
    "estimated_complexity": 23
  },
  "call_locations": [
    {
      "location": "app/models/application_record.rb:12",
      "count": 494,
      "p95_duration_ms": "34.0",
      "p95_row_count": null
    },
    {
      "location": "app/jobs/notification_job.rb:39",
      "count": 1,
      "p95_duration_ms": "31.0",
      "p95_row_count": null
    },
    {
      "location": "app/jobs/cache_warming_job.rb:73",
      "count": 1,
      "p95_duration_ms": "3.0",
      "p95_row_count": null
    },
    {
      "location": "app/jobs/analytics_job.rb:101",
      "count": 1,
      "p95_duration_ms": "28.0",
      "p95_row_count": null
    },
    {
      "location": "app/jobs/data_export_job.rb:66",
      "count": 1,
      "p95_duration_ms": "8.0",
      "p95_row_count": null
    },
    {
      "location": "app/jobs/cleanup_job.rb:32",
      "count": 1,
      "p95_duration_ms": "39.0",
      "p95_row_count": null
    },
    {
      "location": "app/jobs/image_processing_job.rb:114",
      "count": 1,
      "p95_duration_ms": "21.0",
      "p95_row_count": null
    }
  ],
  "n_plus_one": {
    "detected": false
  },
  "index_recommendations": [
    "add_index :users, :active",
    "add_index :posts, :user_id"
  ],
  "issues": [
    "Using SELECT * may retrieve unnecessary columns"
  ]
}