Skip to content

Conversation

veksen
Copy link
Member

@veksen veksen commented Oct 3, 2025

This should probably be done elsewhere but this code lives just prior to the various http endpoints. Happy to move this around however. Defensive frontend code already available in the app in case this isn't available.

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Found New Recommended Indexes

The following indexes are likely to make the most impact to your queries. They're ordered by how many queries seen in your tests

Index Definition Usage Count
assets("event_id", "uploader_id", "inserted_at") 1
guest_ip_addresses("ip_address") 1

Statistics Mode

When generating recommendations, we made the following changes to your database statistics:

fixed rows per table

  • Rows per table: 10000000
  • Pages per table: 1000

Instead of assuming a fixed number of rows per table (which can cause unnecessary recommendations), you can export statistics from your production database and import it using the STATISTICS_PATH environment variable. You can read more about how to sync stats here.

- name: Analyze
  uses: query-doctor/analyzer@v0
  env:
    STATISTICS_PATH: ./statistics.json

Optimization Overview

Query Base Cost Optimized Cost Improvement
3527900520088515000 15922.03 1638.53 9.72x
7119592456364862000 126 9.04 13.94x

Query 3527900520088515000

New indexes improve cost by 9.72x:
  1. assets("event_id", "uploader_id", "inserted_at")
View Query (too long to display inline)
select
  "guests"."id",
  "guests"."session_id",
  "guests"."username",
  "guests"."avatar_path",
  "guests"."color",
  "guests"."side",
  "guests"."audio_recording_path",
  "guests"."audio_recording_public",
  "guests"."memo",
  "guests"."memo_public",
  "guests"."setup_at",
  "guests"."last_upload",
  "guests"."inserted_at",
  "guests"."updated_at",
  "userAssets"."id",
  "userAssets"."kind",
  "userAssets"."event_id",
  "userAssets"."uploader_id",
  "userAssets"."uploader_ip",
  "userAssets"."path",
  "userAssets"."file_size",
  "userAssets"."width",
  "userAssets"."height",
  "userAssets"."visible_at",
  "userAssets"."deleted_at",
  "userAssets"."inserted_at",
  "userAssets"."updated_at"
from
  (
    select
      "id",
      "session_id",
      "username",
      "avatar_path",
      "color",
      "side",
      "audio_recording_path",
      "audio_recording_public",
      "memo",
      "memo_public",
      "setup_at",
      "last_upload",
      "inserted_at",
      "updated_at"
    from
      "guests"
    order by
      "guests"."last_upload" desc,
      "guests"."id" desc
    limit
      100
  ) "guests"
  cross join lateral (
    select
      "id",
      "kind",
      "event_id",
      "uploader_id",
      "uploader_ip",
      "path",
      "file_size",
      "width",
      "height",
      "visible_at",
      "deleted_at",
      "inserted_at",
      "updated_at"
    from
      "assets"
    where
      (
        "assets"."event_id" = (
          select
            "id"
          from
            "events"
          where
            "events"."event_key" = '01JKCVP4M2CH34SVTQGHSW4Y5G'
        )
        and "assets"."uploader_id" = "guests"."id"
      )
    order by
      "assets"."inserted_at" desc
    limit
      100
  ) "userAssets";
View Explain Plan (before optimization)
{
  "Node Type": "Nested Loop",
  "Parallel Aware": false,
  "Async Capable": false,
  "Join Type": "Inner",
  "Startup Cost": 159.35,
  "Total Cost": 15922.03,
  "Plan Rows": 100,
  "Plan Width": 370,
  "Output": [
    "guests.id",
    "guests.session_id",
    "guests.username",
    "... 23 selected columns omitted ..."
  ],
  "Inner Unique": false,
  "Plans": [
    {
      "Node Type": "Limit",
      "Parent Relationship": "Outer",
      "Parallel Aware": false,
      "Async Capable": false,
      "Startup Cost": 0.16,
      "Total Cost": 1.78,
      "Plan Rows": 100,
      "Plan Width": 238,
      "Output": [
        "guests.id",
        "guests.session_id",
        "guests.username",
        "... 10 selected columns omitted ..."
      ],
      "Plans": [
        {
          "Node Type": "Index Scan",
          "Parent Relationship": "Outer",
          "Parallel Aware": false,
          "Async Capable": false,
          "Scan Direction": "Forward",
          "Index Name": "guests_last_upload_desc_id_desc_index",
          "Relation Name": "guests",
          "Schema": "public",
          "Alias": "guests",
          "Startup Cost": 0.16,
          "Total Cost": 162.16,
          "Plan Rows": 10000,
          "Plan Width": 238,
          "Output": [
            "guests.id",
            "guests.session_id",
            "guests.username",
            "... 10 selected columns omitted ..."
          ]
        }
      ]
    },
    {
      "Node Type": "Limit",
      "Parent Relationship": "Inner",
      "Parallel Aware": false,
      "Async Capable": false,
      "Startup Cost": 159.19,
      "Total Cost": 159.19,
      "Plan Rows": 1,
      "Plan Width": 132,
      "Output": [
        "assets.id",
        "assets.kind",
        "assets.event_id",
        "... 9 selected columns omitted ..."
      ],
      "Plans": [
        {
          "Node Type": "Index Scan",
          "Parent Relationship": "InitPlan",
          "Subplan Name": "InitPlan 1 (returns $0)",
          "Parallel Aware": false,
          "Async Capable": false,
          "Scan Direction": "Forward",
          "Index Name": "events_event_key_index",
          "Relation Name": "events",
          "Schema": "public",
          "Alias": "events",
          "Startup Cost": 0.16,
          "Total Cost": 8.18,
          "Plan Rows": 1,
          "Plan Width": 8,
          "Output": [
            "events.id"
          ],
          "Index Cond": "(events.event_key = '01JKCVP4M2CH34SVTQGHSW4Y5G'::text)"
        },
        {
          "Node Type": "Sort",
          "Parent Relationship": "Outer",
          "Parallel Aware": false,
          "Async Capable": false,
          "Startup Cost": 151.01,
          "Total Cost": 151.01,
          "Plan Rows": 1,
          "Plan Width": 132,
          "Output": [
            "assets.id",
            "assets.kind",
            "assets.event_id",
            "... 9 selected columns omitted ..."
          ],
          "Sort Key": [
            "assets.inserted_at DESC"
          ],
          "Plans": [
            {
              "Node Type": "Seq Scan",
              "Parent Relationship": "Outer",
              "Parallel Aware": false,
              "Async Capable": false,
              "Relation Name": "assets",
              "Schema": "public",
              "Alias": "assets",
              "Startup Cost": 0,
              "Total Cost": 151,
              "Plan Rows": 1,
              "Plan Width": 132,
              "Output": [
                "assets.id",
                "assets.kind",
                "assets.event_id",
                "... 9 selected columns omitted ..."
              ],
              "Filter": "((assets.event_id = $0) AND (assets.uploader_id = guests.id))"
            }
          ]
        }
      ]
    }
  ]
}
View Explain Plan (after optimization)
{
  "Node Type": "Nested Loop",
  "Parallel Aware": false,
  "Async Capable": false,
  "Join Type": "Inner",
  "Startup Cost": 8.5,
  "Total Cost": 1638.53,
  "Plan Rows": 100,
  "Plan Width": 370,
  "Output": [
    "guests.id",
    "guests.session_id",
    "guests.username",
    "... 23 selected columns omitted ..."
  ],
  "Inner Unique": false,
  "Plans": [
    {
      "Node Type": "Limit",
      "Parent Relationship": "Outer",
      "Parallel Aware": false,
      "Async Capable": false,
      "Startup Cost": 0.16,
      "Total Cost": 1.78,
      "Plan Rows": 100,
      "Plan Width": 238,
      "Output": [
        "guests.id",
        "guests.session_id",
        "guests.username",
        "... 10 selected columns omitted ..."
      ],
      "Plans": [
        {
          "Node Type": "Index Scan",
          "Parent Relationship": "Outer",
          "Parallel Aware": false,
          "Async Capable": false,
          "Scan Direction": "Forward",
          "Index Name": "guests_last_upload_desc_id_desc_index",
          "Relation Name": "guests",
          "Schema": "public",
          "Alias": "guests",
          "Startup Cost": 0.16,
          "Total Cost": 162.16,
          "Plan Rows": 10000,
          "Plan Width": 238,
          "Output": [
            "guests.id",
            "guests.session_id",
            "guests.username",
            "... 10 selected columns omitted ..."
          ]
        }
      ]
    },
    {
      "Node Type": "Limit",
      "Parent Relationship": "Inner",
      "Parallel Aware": false,
      "Async Capable": false,
      "Startup Cost": 8.34,
      "Total Cost": 16.36,
      "Plan Rows": 1,
      "Plan Width": 132,
      "Output": [
        "assets.id",
        "assets.kind",
        "assets.event_id",
        "... 9 selected columns omitted ..."
      ],
      "Plans": [
        {
          "Node Type": "Index Scan",
          "Parent Relationship": "InitPlan",
          "Subplan Name": "InitPlan 1 (returns $0)",
          "Parallel Aware": false,
          "Async Capable": false,
          "Scan Direction": "Forward",
          "Index Name": "events_event_key_index",
          "Relation Name": "events",
          "Schema": "public",
          "Alias": "events",
          "Startup Cost": 0.16,
          "Total Cost": 8.18,
          "Plan Rows": 1,
          "Plan Width": 8,
          "Output": [
            "events.id"
          ],
          "Index Cond": "(events.event_key = '01JKCVP4M2CH34SVTQGHSW4Y5G'::text)"
        },
        {
          "Node Type": "Index Scan",
          "Parent Relationship": "Outer",
          "Parallel Aware": false,
          "Async Capable": false,
          "Scan Direction": "Forward",
          "Index Name": "__qd_public_assets_event_id_uploader_id_inserted_at",
          "Relation Name": "assets",
          "Schema": "public",
          "Alias": "assets",
          "Startup Cost": 0.16,
          "Total Cost": 8.18,
          "Plan Rows": 1,
          "Plan Width": 132,
          "Output": [
            "assets.id",
            "assets.kind",
            "assets.event_id",
            "... 9 selected columns omitted ..."
          ],
          "Index Cond": "((assets.event_id = $0) AND (assets.uploader_id = guests.id))"
        }
      ]
    }
  ]
}

Query 7119592456364862000

New indexes improve cost by 13.94x:
  1. guest_ip_addresses("ip_address")
select
  *
from
  guest_ip_addresses
where
  ip_address = '127.0.0.1';
View Explain Plan (before optimization)
{
  "Node Type": "Seq Scan",
  "Parallel Aware": false,
  "Async Capable": false,
  "Relation Name": "guest_ip_addresses",
  "Schema": "public",
  "Alias": "guest_ip_addresses",
  "Startup Cost": 0,
  "Total Cost": 126,
  "Plan Rows": 50,
  "Plan Width": 56,
  "Output": [
    "id",
    "guest_id",
    "ip_address",
    "inserted_at"
  ],
  "Filter": "(guest_ip_addresses.ip_address = '127.0.0.1'::text)"
}
View Explain Plan (after optimization)
{
  "Node Type": "Index Scan",
  "Parallel Aware": false,
  "Async Capable": false,
  "Scan Direction": "Forward",
  "Index Name": "__qd_public_guest_ip_addresses_ip_address",
  "Relation Name": "guest_ip_addresses",
  "Schema": "public",
  "Alias": "guest_ip_addresses",
  "Startup Cost": 0.16,
  "Total Cost": 9.04,
  "Plan Rows": 50,
  "Plan Width": 56,
  "Output": [
    "id",
    "guest_id",
    "ip_address",
    "inserted_at"
  ],
  "Index Cond": "(guest_ip_addresses.ip_address = '127.0.0.1'::text)"
}

What are the numbers next to the query? The numbers are a fingerprint uniquely identifying the query. Let us know in the Discord if you'd like to be able to assign unique names to your queries.
What is cost? Cost is an arbitrary value representing the amount of work postgres decided it needs to do to execute a query based on what it knows about the database and the query itself.
We use cost to look for improvements when checking if an index helps optimize a query in CI as the full production dataset is simply not available to work with.
Execution metadata
Log size
204783 bytes
Time elapsed
2186ms
Queries Seen
25
Queries matched
9
Queries optimized
2

@veksen veksen merged commit 73f7d41 into main Oct 9, 2025
3 checks passed
@veksen veksen deleted the feat-provide-formatted-query branch October 9, 2025 15:39
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.

1 participant