What is the performance impact of Shopware's offset-based pagination when querying large datasets with Criteria::limit()?
0 reputation · 27 Jun 2023, 04:04 UTC
0 reputation · 27 Jun 2023, 04:04 UTC
Shopware 6.x uses a Criteria pattern for entity queries with offset-based pagination via Criteria::limit($size, $offset). When retrieving paginated results, the framework executes a separate COUNT query to calculate the total number of records, which can become expensive for large datasets, especially with complex joins or unindexed tables.
The EntitySearchResult::getTotal() method returns this calculated total, but the COUNT operation itself may not scale well as dataset size increases. Shopware's native pagination does not support cursor-based alternatives, relying solely on offset-based navigation.
For custom entity definitions, overriding getListing() allows implementing alternative pagination strategies, but the default behavior remains bound to the traditional COUNT + LIMIT/OFFSET approach. This becomes particularly problematic when paginating beyond the first few hundred records, where OFFSET values grow large and database performance degrades.
Key Questions:
32275 reputation · 27 Jun 2023, 09:46 UTC
When you use Criteria::limit($size, $offset) in Shopware 6, the framework executes two separate SQL statements for each paginated request:
COUNT(*) query to calculate the total number of matching rows.SELECT … LIMIT … OFFSET … query that fetches the current page.Both operations add measurable overhead. The COUNT query can become expensive on large tables or when the query contains complex joins or non‑indexed filters. The OFFSET forces the database engine to scan and skip all preceding rows, which grows linearly with the offset value. In typical MySQL 8.0 setups, offsets beyond a few thousand rows (≈5 000–10 000) already start to degrade latency noticeably; for datasets over 50 000 rows the combined cost of COUNT + OFFSET often dominates the total response time.
COUNT(*) query.OFFSET causes full row‑scan up to the offset point; if an index can be used, the engine may still need to perform a filesort.COUNT and LIMIT/OFFSET is a measurable bottleneck in production.getListing() or write custom repository methods.COUNT cost, but the OFFSET penalty remains.EXPLAIN (FORMAT JSON) on the generated SQL to see whether the engine uses a filesort or can use an index for the offset.COUNT query and the LIMIT/OFFSET query separately on a copy of the dataset. Compare the times as the offset increases.WHERE clauses of the Criteria are indexed. Missing indexes inflate both COUNT and offset costs.id or a timestamp) to fetch the next page with WHERE id > lastId ORDER BY id ASC LIMIT size. This eliminates the offset penalty.To refine the recommendation, could you tell me which database engine you’re using (MySQL, MariaDB, PostgreSQL, etc.)? The threshold where offset becomes a bottleneck varies with the engine’s query planner.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.