Índices
Crear índices en x.id
y y.id
- que probablemente ya tenga si esas son sus claves principales.
Un índice de varias columnas también puede ayudar, especialmente con indexar solo escaneos
en la página 9.2+:
CREATE INDEX y_mult_idx ON y (id DESC, val)
Sin embargo, en mis pruebas, este índice no se utilizó al principio. Tuve que agregar (de lo contrario sin sentido) val
a ORDER BY
para convencer al planificador de consultas de que el orden de clasificación coincide. Ver consulta 3 .
El índice hace poca diferencia en esta configuración sintética. Pero para tablas con más columnas, recuperando val
de la tabla se vuelve cada vez más caro, lo que hace que el índice de "cobertura" sea más atractivo.
Consultas
1) Sencillo
SELECT DISTINCT ON (x.id)
x.id, y.val
FROM x
JOIN y ON y.id <= x.id
ORDER BY x.id, y.id DESC;
Más explicación de la técnica con DISTINCT
en esta respuesta relacionada:
Realicé algunas pruebas porque tenía mis sospechas de que la primera consulta no escalaría bien. Es rápido con una mesa pequeña, pero no es bueno con mesas más grandes. Postgres no optimiza el plan y comienza con una unión cruzada (limitada), con un costo de O(N²)
.
2) Rápido
Esta consulta sigue siendo bastante simple y escala de manera excelente:
SELECT x.id, y.val
FROM x
JOIN (SELECT *, lead(id, 1, 2147483647) OVER (ORDER BY id) AS next_id FROM y) y
ON x.id >= y.id
AND x.id < y.next_id
ORDER BY 1;
La función de ventana lead()
es instrumental. Hago uso de la opción para proporcionar un valor predeterminado para cubrir la esquina de la última fila:2147483647
es el entero más grande posible
. Adaptarse a su tipo de datos.
3) Muy simple y casi igual de rápido
SELECT x.id
,(SELECT val FROM y WHERE id <= x.id ORDER BY id DESC, val LIMIT 1) AS val
FROM x;
Normalmente, subconsultas correlacionadas tienden a ser lentos. Pero este solo puede elegir un valor del índice (de cobertura) y, por lo demás, es tan simple que puede competir.
El ORDER BY
adicional elemento val
(énfasis en negrita) parece inútil. Pero agregarlo convence al planificador de consultas de que está bien usar el índice de varias columnas y_mult_idx
desde arriba, porque el orden de clasificación coincide. Tenga en cuenta el
en el EXPLAIN
salida.
Caso de prueba
Después de un animado debate y varias actualizaciones, recopilé todas las consultas publicadas hasta el momento e hice un caso de prueba para obtener una descripción general rápida. Solo uso 1000 filas para que SQLfiddle no se agote con las consultas más lentas. Pero los 4 primeros (Erwin 2, Clodoaldo, a_horse, Erwin 3) escalan linealmente en todas mis pruebas locales. Actualizado una vez más para incluir mi última incorporación, mejorar el formato y ordenar por rendimiento ahora:
Violín Big SQL comparando el rendimiento.