You've already forked AstralRinth
forked from didirus/AstralRinth
perf(labrinth/random_projects_get): speed up through spatial queries according to profiling results (#3762)
This commit is contained in:
committed by
GitHub
parent
858c7e393f
commit
a3839461cf
@@ -519,6 +519,9 @@ impl ProjectStatus {
|
||||
}
|
||||
|
||||
// Project can be displayed in search
|
||||
// IMPORTANT: if this is changed, make sure to update the `mods_searchable_ids_gist`
|
||||
// index in the DB to keep random project queries fast (see the
|
||||
// `20250609134334_spatial-random-project-index.sql` migration)
|
||||
pub fn is_searchable(&self) -> bool {
|
||||
matches!(self, ProjectStatus::Approved | ProjectStatus::Archived)
|
||||
}
|
||||
|
||||
@@ -94,12 +94,16 @@ pub async fn random_projects_get(
|
||||
})?;
|
||||
|
||||
let project_ids = sqlx::query!(
|
||||
// IDs are randomly generated (see the `generate_ids` macro), so ID order is
|
||||
// equivalent to a random order
|
||||
"SELECT id FROM mods WHERE status = ANY($1)
|
||||
ORDER BY id
|
||||
LIMIT $2
|
||||
OFFSET GREATEST(ROUND(RANDOM() * (SELECT COUNT(*) FROM mods WHERE status = ANY($1)))::int8 - $2, 0)",
|
||||
// IDs are randomly generated (see the `generate_ids` macro), so fetching a
|
||||
// number of mods nearest to a random point in the ID space is equivalent to
|
||||
// random sampling
|
||||
"WITH random_id_point AS (
|
||||
SELECT POINT(RANDOM() * ((SELECT MAX(id) FROM mods) - (SELECT MIN(id) FROM mods) + 1) + (SELECT MIN(id) FROM mods), 0) AS point
|
||||
)
|
||||
SELECT id FROM mods
|
||||
WHERE status = ANY($1)
|
||||
ORDER BY POINT(id, 0) <-> (SELECT point FROM random_id_point)
|
||||
LIMIT $2",
|
||||
&*crate::models::projects::ProjectStatus::iterator()
|
||||
.filter(|x| x.is_searchable())
|
||||
.map(|x| x.to_string())
|
||||
|
||||
Reference in New Issue
Block a user