sql >> Databáze >  >> RDS >> PostgreSQL

Jak mohu napsat spojení s těmito neobvyklými kritérii shody?

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;

SQL Fiddle.

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.



  1. Měli byste v SQL Serveru zvolit datové typy MONEY nebo DECIMAL(x,y)?

  2. PostgreSQL ZOBRAZIT TABULKY Ekvivalent (psql)

  3. chyba při vkládání dat VELKÉHO objemu do mysql pomocí node.js (kód chyby:'ECONNRESET')

  4. Co je funkce s hodnotou tabulky v SQL Server?