Indexy
Vytvořte indexy na x.id
a y.id
- které pravděpodobně již máte, pokud se jedná o vaše primární klíče.
Vícesloupcový index může také pomoci, zejména s pouze prohledávání indexu
na str. 9.2+:
CREATE INDEX y_mult_idx ON y (id DESC, val)
V mých testech se však tento index zpočátku nepoužíval. Musel přidat (jinak zbytečné) val
do ORDER BY
přesvědčit plánovač dotazů, že pořadí řazení odpovídá. Viz dotaz 3 .
Index má v tomto syntetickém nastavení malý rozdíl. Ale pro tabulky s více sloupci načítání val
od stolu se stává stále dražší, čímž se "krycí" index stává atraktivnějším.
Dotazy
1) Jednoduché
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;
Další vysvětlení techniky pomocí DISTINCT
v této související odpovědi:
Provedl jsem několik testů, protože jsem měl podezření, že první dotaz nebude dobře škálovat. S malým stolem je to rychlé, ale s většími stoly to nejde. Postgres neoptimalizuje plán a začíná (omezeným) křížovým spojením s cenou O(N²)
.
2) Rychlé
Tento dotaz je stále poměrně jednoduchý a výborně se škáluje:
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;
Funkce okna lead()
je instrumentální. Využívám možnost poskytnout výchozí nastavení pro pokrytí rohového pouzdra posledního řádku:2147483647
je největší možné celé číslo
. Přizpůsobte se vašemu datovému typu.
3) Velmi jednoduché a téměř stejně rychlé
SELECT x.id
,(SELECT val FROM y WHERE id <= x.id ORDER BY id DESC, val LIMIT 1) AS val
FROM x;
Obvykle korelované poddotazy bývají pomalé. Ale tento může jen vybrat hodnotu z (krycího) indexu a jinak je tak jednoduchý, že může konkurovat.
Další ORDER BY
položka val
(tučný důraz) se zdá být zbytečné. Jeho přidání však přesvědčí plánovač dotazů, že je v pořádku použít vícesloupcový index y_mult_idx
shora, protože pořadí řazení odpovídá. Všimněte si
v EXPLAIN
výstup.
Testovací případ
Po živé debatě a několika aktualizacích jsem shromáždil všechny dosud zaslané dotazy a vytvořil testovací případ pro rychlý přehled. Používám pouze 1000 řádků, takže SQLfiddle nevyprší s pomalejšími dotazy. Ale nejlepší 4 (Erwin 2, Clodoaldo, a_horse, Erwin 3) se lineárně škálují ve všech mých místních testech. Znovu aktualizováno, aby zahrnovalo můj nejnovější přírůstek, zlepšil formát a pořadí podle výkonu nyní:
Big SQL Fiddle porovnávání výkonu.