diff --git a/backend/app/services/showcase_service.py b/backend/app/services/showcase_service.py index f34051b..e60870c 100644 --- a/backend/app/services/showcase_service.py +++ b/backend/app/services/showcase_service.py @@ -20,11 +20,20 @@ class ShowcaseService: async def random_sample(self, limit: int = 60) -> list[dict]: if limit < 1 or limit > 200: raise ValueError("limit must be between 1 and 200") + # Over-sample then random-order (#699): SYSTEM_ROWS reads CONTIGUOUS rows + # from each sampled page, so sequentially-imported near-duplicates + # (multi-image posts, variant sets) come back adjacent and cluster in the + # showcase ("three near-identical in a row"). Sampling a multiple of + # `limit` spans more pages, and ORDER BY random() before taking `limit` + # breaks the physical adjacency — far better spread, still cheap + # (random() over a few hundred rows, not the whole table). + oversample = min(limit * 5, 1000) stmt = select(ImageRecord).from_statement( text( - "SELECT * FROM image_record " - "TABLESAMPLE SYSTEM_ROWS(:n)" - ).bindparams(n=limit) + "SELECT * FROM (" + " SELECT * FROM image_record TABLESAMPLE SYSTEM_ROWS(:o)" + ") sub ORDER BY random() LIMIT :n" + ).bindparams(o=oversample, n=limit) ) rows = (await self.session.execute(stmt)).scalars().all() return [