Je to v podstatě jen uložený SELECT
dotaz, který se spustí pokaždé, když se na pohled dotážeme. Pohled neukládá žádná data. Vždy zobrazuje aktuální data z podkladových tabulek. Jakákoli změna v tabulkách se okamžitě projeví v pohledu. Může být pomalý, zejména u složitých dotazů (např. s JOIN
y nebo agregacemi), protože dotaz se musí provést při každém použití. Ideální je pro zjednodušení složitých dotazů, omezení přístupu k určitým sloupcům nebo řádkům a zajištění, že vždy pracujete s nejčerstvějšími daty.
Pokud vytvoříte pohled aktivni_uzivatele
, který vybírá uživatele se status = 'active'
, dotaz na tento pohled pokaždé prohledá tabulku uzivatele
a vrátí aktuální seznam aktivních uživatelů.
Pohledy umožňují detailní kontrolu nad přístupem k datům. Můžete vytvářet pohledy, které zobrazují podmnožiny dat v základních tabulkách a skrývají citlivé informace. To je obzvláště užitečné, když máte aplikace, které vyžadují přístup k různým částem dat.
Pokud vaše aplikace používají pohledy (views), můžete volně upravovat strukturu základních tabulek. Jinými slovy, views vám umožňují vytvořit vrstvu nad podkladovými tabulkami.
CREATE VIEW contact AS
SELECT
first_name,
last_name,
email
FROM
customer;
Ukládá fyzickou kopii výsledku dotazu na disk, podobně jako skutečná tabulka. Data jsou statická a neodrážejí změny v podkladových tabulkách, dokud není pohled explicitně obnoven (refreshnutý). Materialized Views jsou velmi rychlé, protože čtení dat probíhá z již předpočítané a uložené sady výsledků. Nemusí se tedy provádět složitý dotaz.
Je to perfektní pro analytické a reportovací dotazy nad velkými objemy dat, kde je výkon kritický a data nemusí být aktuální na sekundu přesně (např. denní reporty, dashboardy).
Pokud vytvoříte materializovaný pohled denni_report_prodeje
, který sčítá prodeje za každý den, data v něm zůstanou stejná, dokud nespustíte příkaz REFRESH MATERIALIZED VIEW denni_report_prodeje;
. To se typicky dělá v naplánovaných intervalech (např. každou noc) nějakou službou.
Hlavním a nejdůležitějším důvodem je dramatické zvýšení výkonu (rychlosti) u složitých a časově náročných dotazů. Představte si, že máte dotaz, který spojuje několik velkých tabulek a počítá složité agregace (např. SUM
, AVG
, COUNT
). Spuštění takového dotazu může trvat sekundy, minuty, nebo dokonce déle.
Pokud použijete běžný view, dotaz se spustí pokaždé, když se na view podíváte. Pokud na tento view přistupuje 10 uživatelů současně, databáze ho musí 10krát přepočítat.
Pokud použijete materializované view, dotaz se spustí pouze jednou při jeho obnovení (REFRESH
). Všechny dotazy na tento view pak už jen čtou předpočítané, uložené výsledky, což je extrémně rychlé – prakticky stejně rychlé jako čtení z běžné tabulky.
Použijte ho, když platí následující:
SELECT
dotaz je sám o sobě příliš pomalý pro běžné použití.Reporty a analýzy: Vytváření denních, týdenních nebo měsíčních souhrnů prodejů, návštěvnosti webu atd. Tyto reporty stačí generovat jednou za čas (např. každou noc).
Dashboardy: Zobrazovací panely (např. v nástrojích jako Grafana nebo Tableau), které ukazují klíčové metriky. Uživatelé je neustále obnovují a bez materializovaného pohledu byste "uvařili" databázi.
Snížení zátěže produkční databáze: Můžete přesunout náročné analytické výpočty do materializovaného pohledu, který se obnovuje v době nízké zátěže (např. v noci), a tím uvolnit zdroje pro hlavní provoz aplikace.
API, která musí rychle odpovídat: Pokud potřebujete přes API poskytovat nějaká agregovaná data, čtení z materializovaného pohledu zajistí bleskovou odezvu.
Zjednodušeně řečeno materializovaný view je forma inteligentního cachování (ukládání do mezipaměti) přímo na úrovni databáze. Obětujete aktuálnost dat za cenu obrovského nárůstu rychlosti čtení.
CREATE MATERIALIZED VIEW rental_by_category
AS
SELECT c.name AS category,
sum(p.amount) AS total_sales
FROM (((((payment p
JOIN rental r ON ((p.rental_id = r.rental_id)))
JOIN inventory i ON ((r.inventory_id = i.inventory_id)))
JOIN film f ON ((i.film_id = f.film_id)))
JOIN film_category fc ON ((f.film_id = fc.film_id)))
JOIN category c ON ((fc.category_id = c.category_id)))
GROUP BY c.name
ORDER BY sum(p.amount) DESC
WITH NO DATA;
REFRESH MATERIALIZED VIEW rental_by_category;
© Josef Novotný 2025