Yeda AI Tips · #134

English

Cambia la paginación por offset por la de keyset

En una tabla grande y cambiante, la paginación por offset es un bug esperando a ocurrir. LIMIT 20 OFFSET 100 parece inofensivo en una revisión de código. No lo es. En una tabla grande y mutable hace dos cosas que nadie quiere: se vuelve más lenta con cada página y salta y repite filas en silencio mientras la gente sigue insertando y borrando debajo de ti. La paginación por keyset arregla ambas — y es el patrón que los revisores esperan una vez que tu tabla deja de ser pequeña.

Por qué el offset se desfasa

OFFSET N le dice a la base de datos: trae las filas en orden y luego descarta las primeras N. De esa sola frase salen dos consecuencias.

Avanza por clave, no por posición

La paginación por keyset (también llamada seek o cursor) nunca cuenta posiciones. Recuerda la clave de orden de la última fila de la página y pide las filas posteriores a esa clave:

-- Page 1
SELECT id, title, created_at
FROM articles
ORDER BY created_at DESC, id DESC
LIMIT 20;

-- Next page: pass the last row's (created_at, id) back in
SELECT id, title, created_at
FROM articles
WHERE (created_at, id) < (:last_created_at, :last_id)
ORDER BY created_at DESC, id DESC
LIMIT 20;

La cláusula WHERE se ancla a un valor, no a un conteo, así que las inserciones y borrados en otras partes de la tabla no pueden mover tu límite. Y con un índice sobre (created_at, id), la base de datos salta directo al ancla en lugar de recorrer todo lo anterior — la página 5.000 cuesta lo mismo que la página 1.

La única regla que lo hace funcionar

El keyset necesita un orden de clasificación explícito, único y estable. Nunca dependas del orden implícito — una consulta sin ORDER BY devuelve las filas en el orden físico que el motor prefiera, y ese orden puede cambiar debajo de ti.

Columna de ordenProblemaSolución
created_at solaLos timestamps colisionan; los empates se saltan o repiten en los bordes de páginaAgrega un desempate único: ORDER BY created_at DESC, id DESC
name, price, cualquier campo no únicoLa misma colisión en los límitesAgrega la clave primaria para romper empates
Sin ORDER BYEl orden es indefinido e inestableOrdena siempre de forma explícita

Toda la garantía descansa en que el cursor apunte a exactamente una fila. Cualquier columna de orden no única necesita que se le agregue la clave primaria para que la tupla (sort_key, id) sea única.

Notas para usuarios avanzados

Recursos

¿Desarrollas funciones con muchos datos? Yeda AI diseña, audita y despliega backends de producción que se mantienen correctos a escala.

Habla con nosotros · Lee el blog