Při načítání všech nebo většiny řádků z tabulky je nejrychlejším způsobem pro tento typ dotazu obvykle nejprve agregovat / rozčlenit a připojte se později :
SELECT *
FROM products p
JOIN (
SELECT DISTINCT ON (product_id) *
FROM meta
ORDER BY product_id, id DESC
) m ON m.product_id = p.id;
Čím více řádků v meta
na řádek v products
, tím větší bude dopad na výkon.
Samozřejmě budete chtít přidat ORDER BY
klauzule v poddotazu definujte který řádek pro výběr z každé sady v poddotazu. @Craig a @Clodoaldo vám o tom již řekli. Vracím meta
řádek s nejvyšším id
.
SQL Fiddle.
Podrobnosti pro DISTINCT ON
:
- Vybrat první řádek v každé skupině GROUP BY?
Optimalizace výkonu
Přesto to není vždy nejrychlejší řešení. V závislosti na distribuci dat existují různé další styly dotazů. V tomto jednoduchém případě zahrnujícím další spojení tento běžel podstatně rychleji v testu s velkými stoly:
SELECT p.*, sub.meta_id, m.product_id, m.price, m.flag
FROM (
SELECT product_id, max(id) AS meta_id
FROM meta
GROUP BY 1
) sub
JOIN meta m ON m.id = sub.meta_id
JOIN products p ON p.id = sub.product_id;
Pokud byste nepoužili nepopisné id
jako názvy sloupců bychom nenarazili na kolize pojmenování a mohli bychom jednoduše napsat SELECT p.*, m.*
. (Já nikdy použijte id
jako název sloupce.)
Pokud je vaším prvořadým požadavkem výkon, zvažte další možnosti:
- a
MATERIALIZED VIEW
s předem agregovanými daty zmeta
, pokud se vaše data nezmění (příliš). - rekurzivní CTE emulující volné skenování indexu na velké
meta
tabulka s mnoha řádků na produkt (relativně málo odlišnýchproduct_id
).
Toto je jediný způsob, jak znám použít index pro DISTINCT dotaz na celou tabulku.