sql >> Base de Datos >  >> RDS >> PostgreSQL

¿Cómo escribo una combinación con este criterio de coincidencia inusual?

Í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;

SQL Fiddle.

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.