Repository navigation
perf(audit-logs): index organization-level rows and read them as two keyset parts - #9437
Merged
Merged
Conversation
…keyset parts The organization listing reads its organization-level rows as one keyset branch: workspace_id IS NULL and (metadata organizationId = org, or the organization resource itself). No index served that branch, so the planner seeked workspace_id IS NULL and filtered every workspace-less row in the table, spread across the heap. An organization without a page of such rows near the top paid for all of them on every request. A partial expression index on (metadata->>'organizationId', the millisecond created_at, id) over workspace-less rows that carry the key now serves the metadata match, and the branch is split into two disjoint parts so that part can be read in keyset order and stop after a page: the metadata match, and the organization-resource match whose metadata does not already name the organization (a few rows, on audit_log_resource_idx). Disjointness keeps the union exact; buildOrgScopeCondition keeps its predicate. The index alone is not enough: under the single OR the planner can only BitmapOr the two indexes and sort, which reads every organization-level row of the organization. The existing list-scope suite compared results only, which the slow plan returns correctly; a plan suite now asserts the metadata part is read through the new index, never by a workspace_id IS NULL seek, and that the index can stream it backward in keyset order. The scope suite gains rows matching both parts, only the resource part, and another organization.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
[Medium impact] The PR appears safe to merge, with no actionable issues found. SummaryAdds an index for organization-level audit rows and splits their listing into two non-overlapping parts.
|
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes a regression from #9419 in the organization audit-log listing.
workspace_id IS NULLand the org named in metadata or as the resource). No index served that branch in order, so unless the organization had a page of org-level rows near the top, every listing walked every workspace-less audit row in the table, scattered across the heap. Listings got slower and long reads on the replica began hitting recovery-conflict cancellationsaudit_log_org_level_created_at_id_idx, a partial index on(metadata->>'organizationId', date_trunc('milliseconds', created_at), id) WHERE workspace_id IS NULL AND metadata->>'organizationId' IS NOT NULL. It's built concurrently with the replay-safe invalid-index handling from 0442, and it only holds workspace-less rows that name an organizationaudit_log_resource_idx, a handful per org). The index alone isn't enough: under the singleORthe planner bitmap-ORs both indexes and sorts every org-level row of the organizationbuildOrgScopeCondition(single-record read, data drain) is unchanged and shares the same two definitions of an org-level rowType of Change
Testing
list-plans.integration.ts: many workspace-less rows from other organizations, then EXPLAINs the SQLqueryAuditLogssends (current members and departed, with and without a cursor). It asserts the metadata part reads the new index and nothing seeksworkspace_id IS NULL, and that the index serves it as a backward scan with the cursor in the index condition. Fails on the previous querylist-scope.integration.tsadds metadata-only, resource-only and both-matching rows (appear once) and a resource row naming another org, and pages across all parts at several page sizes against the single-predicate referencebun run lint,type-check,check:audits,check-test-types,check:migrations, drizzle-kit generate (no changes)Checklist