Skip to content

perf(packages): add (ref_type, ref_id) index to package_property - #39465

Open
UnderwaterOverground wants to merge 3 commits into
go-gitea:mainfrom
UnderwaterOverground:package-property-ref-index
Open

UnderwaterOverground wants to merge 3 commits into
go-gitea:mainfrom
UnderwaterOverground:package-property-ref-index

Conversation

@UnderwaterOverground

Copy link
Copy Markdown

Every package property lookup (GetProperties, GetPropertiesByName, InsertOrUpdateProperty, DeleteAllProperties, ...) filters on ref_type and ref_id, but package_property only has single-column indexes on ref_type, ref_id and name.

On SQLite, which has no ANALYZE statistics unless someone runs it manually, the planner has no way to tell those indexes apart. On my instance it picked IDX_package_property_ref_type, which has only three distinct values, so every lookup scanned all ~30k file properties. Container ListPackages calls (GET /api/v1/packages/{owner}?type=container&q=...) took 14–22 s each and showed up as [Slow SQL Query] in the logs.

This adds a composite (ref_type, ref_id) index plus migration 356. name is deliberately left out: GetProperties orders by id, and in my tests SQLite still chose the single-column index over (ref_type, ref_id, name).

Measured on a copy of the affected production SQLite DB (SQLite 3.50.4, no sqlite_stat1), 300 × SELECT ... FROM package_property WHERE ref_type = 1 AND ref_id = ? ORDER BY id:

Indexes Plan Time
current USING INDEX IDX_package_property_ref_type (ref_type=?) 983 ms
+ (ref_type, ref_id, name) unchanged (ref_type) 980 ms
+ (ref_type, ref_id) (this PR) USING INDEX IDX_package_property_ref (ref_type=? AND ref_id=?) 13 ms

After the fix, the API calls went from ~15 s to ~100 ms. Running ANALYZE manually also fixes it, but only until the next time nobody runs it.

Existing single-column indexes are kept (IgnoreDropIndices); ref_id and name are still used by joins and name/value searches elsewhere.

Tests: TestAddPackagePropertyRefIndex (new), go test ./models/packages/....

AI disclosure: I used an AI assistant (Claude) to investigate the slow query, draft the change and write this description. I reviewed the change and reproduced the before/after numbers above on my own instance.

Every package property lookup filters on both ref_type and ref_id, but the
table only has single-column indexes. SQLite has no ANALYZE statistics by
default, so the planner can pick the ref_type index (only three distinct
values) and scan every property of that type for each lookup. On a registry
with ~30k file properties this made container ListPackages API calls take
14-22s.

A composite (ref_type, ref_id) index is chosen regardless of statistics.
It deliberately excludes name: GetProperties orders by id, and SQLite
prefers a single-column index over (ref_type, ref_id, name) for that.
@GiteaBot GiteaBot added the lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. label Sep 28, 2026
@bircni
bircni requested a lite review from Copilot September 28, 2026 21:22

Copilot AI left a comment

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.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

cols = append(cols, idx.Cols)
}
assert.Contains(t, cols, []string{"ref_type", "ref_id"})
assert.Contains(t, cols, []string{"ref_type"})

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.

If ("ref_type", "ref_id") exists, ("ref_type") is just a duplicate and useless.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. topic/packages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants