-
-
Notifications
You must be signed in to change notification settings - Fork 249
Open
Labels
Description
Pagination is insanely slow.
This code:
$items->paginate(25)
and produces:
select t2.* from ( select rownum AS "rn", t1.* from (select * from table where "some_field" is not null and "other_field" is null) t1 ) t2 where t2."rn" between 1 and 25
then takes 23 seconds in PHP or Oracle in our DB of 500k records.
Change to ROW_NUMBER() OVER
select t2.* from ( select ROW_NUMBER() OVER (ORDER BY t1.primary_key_field) AS "rn", t1.* from (select * from table where "some_field" is not null and "other_field" is null) t1 ) t2 where t2."rn" between 1 and 25
and it takes 0.8s.
GPT4 suggests:
protected function compileTableExpression($sql, $constraint, $query)
{
// Case for fetching a single row
if ($query->limit == 1 && is_null($query->offset)) {
return "select * from ({$sql}) where rownum {$constraint}";
}
// Case for pagination with limit and offset
if (!is_null($query->limit) && !is_null($query->offset)) {
$start = $query->offset + 1;
$finish = $query->offset + $query->limit;
// Using ROW_NUMBER() and CTE for efficient pagination
return "
WITH query_cte AS (
SELECT t1.*, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS rn
FROM ({$sql}) t1
)
SELECT *
FROM query_cte
WHERE rn BETWEEN {$start} AND {$finish}
";
}
// Fallback for other cases
return "
WITH query_cte AS (
SELECT t1.*, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS rn
FROM ({$sql}) t1
)
SELECT *
FROM query_cte
WHERE rn {$constraint}
";
}