X36SQL - Jazyk SQL, letní semestr 2009

Marek Handl Čtvrtek 18:00

Prohlašuji, že jsem svou semestrální práci vypracoval samostatně. Všechny zdroje, ze kterých jsem čerpal, jsou uvedeny v části Odkazy.

Systém jezdců na kole

Popis

Charakteristika projektu

Systém je určen pro spíše uzavřenou skupinu uživatelů - jezdců na kole - a slouží pro sdílení informací o jezdcích, závodech, komponentech a obchodech s cyklistickým zbožím. Základem je seznam jezdců, u kterých se sleduje jejich jméno, příjmení, přezdívka a e-mail. Existuje několik jezdeckých disciplín a každý jezdec má alespoň jednu oblíbenou. Ve většině disciplín se jezdí závody, kterých se jezdci mohou zúčastnit. Seznam lokací udržuje informace o oblastech, kde se dají provozovat cyklistické sporty. Další částí je seznam komponent - na výběr jsou 3 komponenty - rám, vidlice a plášť. Každý komponent je určen trojicí: výrobce, model a rok. Komponent má poté další vlastnosti, které zavisejí na druhu komponentu (např. zdvih u vidlice, poloměr kola, pro který je vidlice určena, velikost rámu, poloměr kola, pro který je rámurčen apod.). Jezdec může ke konkrétnímu komponentu napsat svou zkušenost, a to zadáním hodnot poměr cena/výkon, celkové hodnocení a může napsat i nepovinné slovní hodnocení. Mezi jezdcem a komponentem může být navázán vztah vyjadřující skutečnost, že jezdec v současnosti daný komponent využívá (má ho na svém kole). Udržuje se také seznam obchodů s cyklistickými potřebami. Obchod je identifikován svým názvem, povinným parametrem je adresa a jako nepovinný parametr je přidán odkazna případné www stránky. Jezdec může napsat hodnocení obchodu, kde ohodnotí sortiment, ceny, přívětivost a může napsat i slovní ohodnocení. V systému je ještě seznam nákupu. Každý nákup je identifikován čtveřicí - datum, komponent, jezdec a obchod. Dalším parametrem nákupu je cena.

Popis procedurálního rozšíření

- Celková suma nákupů

U každého jezdce budeme udržovat částku, kterou utratil za komponenty. Hodnota bude součtem všech nákupů jezdce, které budou v systému. Částka se bude ukládat jako atribut jezdce a její hodnota bude aktualizována pomocí triggeru.

- Poloměry plášťů

Je nutné zajistit, že poloměry plášťů, které jezdec využívá odpovídají poloměrům, pro které jsou určeny vidlice a rámy používané jezdcem. Tedy pokud jezdec používá vidlici pro poloměr 26", pak musí také používat plášť s poloměrem 26". Obdobně pro rám. Naopak platí, že nemůže používat plášť, který nepasuje do žádné používané vidlice a do žádného používaného rámu. Kontrolu je třeba provádět při přidávání, odebírání a upravovaní komponentů.

- Závod jen v oblíbené disciplíně

Při vkládání informace o účasti na závodu je nutno zajistit, že se jezdec může účastnit pouze závodů v disciplíně, kterou má uvedenu jako oblíbenou.

- Platný rok nákupu

Při zaznamenávání nákupu komponentu se kontroluje, zda je rok z datumu nákupu vyšší nebo roven roku uvedení komponentu na trh.

- Kontrola formátu emailu

Při vkládání nového jezdce nebo při úpravách existujícího se kontroluje email, zda má platný formát emailové adresy.

- Hodnoty hodnocení

Systém zajistí, že hodnoty parametrů poměr cena výkon a hodnocení v seznamu zkušeností a parametrů sortiment, ceny a přívětivost v seznamu hodnocení obchodů jsou celá čísla z rozsahu 1 až 10.

Schéma datového úložiště

ER-Schéma

Diskuse datového modelu a popis integritních omezení

Popis smyček:

Jezdec-Dispciplina-Zavod: Jezdec má různé oblíbené dispciplíny a může se v nich účastnit závodů. Na omezení počtu závodů v disciplínách nejsou kladeny omezení, tedy nemusí se účastnit žádného, ale může se také účastnit i více než jednoho.

Jezdec-Komponent-Nakup: Jezdec může používat i komponenty u kterých nezaznamenal jejich nákup. Tato možnost je tu například proto, že při koupi celého kola nelze rozlišit cenu jednotlivých komponentů. Stejně tak je možné, že jezdec komponent zakoupil, ale již nepoužívá (např. ho prodal).

Jezdec-Komponent-Zkusenost: Důvodem této smyčky je opět skutečnost, že vztah pouziva reprezentuje současný stav, zatímco zkusenost vyjadřuje to, že daný jezdec daný komponent někdy používal.

Zkusenost-Komponent-Nakup: Odůvodnění je stejné jako u předchozí smyčky.

Jezdec-Hodnoceni-Obchod-Nakup: Jezdec může napsat Hodnoceni Obchodu i když neprovedl ještě žádný Nakup. V reálné situaci to může být způsobeno například tím, že koupil věc, která se do naší databáze nezaznamenává, či se byl v Obchode jen podívat.

SQL script pro vytvoření relačního db schématu

Odkaz na script
Odezva

SQL script pro vytvoření objektově relačního db schématu

Odkaz na script
Odezva

PLSQL procedura pro naplnění relačních tabulek

Odkaz na script

PLSQL procedura pro naplnění objektových tabulek

Odkaz na script

10 SQL dotazů dle specifikované složitosti

  1. Dotaz 1

    Seznam názvů obchodů s částkami v nich utracených za nákupy.

    První verze

    SQL

    SELECT nazev, COALESCE(soucet,0) castka FROM obchod LEFT OUTER JOIN (SELECT ob_nazev nazev, SUM(cena) soucet FROM nakup GROUP BY(ob_nazev)) USING(nazev);

    Exekuční plán

    Plan hash value: 3279846785 ---------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 5 | 250 | 5 (40)| 00:00:01 | |* 1 | HASH JOIN OUTER | | 5 | 250 | 5 (40)| 00:00:01 | | 2 | INDEX FULL SCAN | PK_OBCHOD | 5 | 50 | 1 (0)| 00:00:01 | | 3 | VIEW | | 3 | 120 | 3 (34)| 00:00:01 | | 4 | HASH GROUP BY | | 3 | 36 | 3 (34)| 00:00:01 | | 5 | TABLE ACCESS FULL| NAKUP | 7 | 84 | 2 (0)| 00:00:01 | ---------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("OBCHOD"."NAZEV"="from$_subquery$_002"."NAZEV"(+)) Statistics ----------------------------------------------------------- 1 recursive calls 0 db block gets 6 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 1 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    NAZEV CASTKA -------------------------------------------------- ---------------------- Madla Sport 18400 Dookie 14549 901 Bikes 6600 Bike Kellys Seky 0 Katmar 0 5 rows selected

    Diskuse 1

    Odezva na dotaz je správná.

    Diskuse 2

    Dotaz používá náročné vnější polospojení. Zkusíme ho zefektivnit použitím vnořeného dotazu.

    Druhá verze

    SQL

    SELECT nazev, COALESCE((SELECT SUM(cena) FROM nakup N WHERE N.ob_nazev=O.nazev),0) castka FROM obchod O;

    Exekuční plán

    Plan hash value: 1153909728 -------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 5 | 50 | 1 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 12 | | | |* 2 | TABLE ACCESS FULL| NAKUP | 2 | 24 | 2 (0)| 00:00:01 | | 3 | INDEX FULL SCAN | PK_OBCHOD | 5 | 50 | 1 (0)| 00:00:01 | -------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("N"."OB_NAZEV"=:B1) Statistics ----------------------------------------------------------- 1 recursive calls 0 db block gets 26 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 1 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    NAZEV CASTKA -------------------------------------------------- ---------------------- 901 Bikes 6600 Bike Kellys Seky 0 Dookie 14549 Katmar 0 Madla Sport 18400 5 rows selected

    Diskuse 1

    Odezva je správná. Od první verze se ale liší pořadím.

    Diskuse 2

    Druhá verze je znatelně efektivnější. Verze 2 je opravdu efektivnější, cena dotazu je o 3/8 levnější. Množinový rozdíl je méně efektivní, než použití poddotazu s negativním predikátem. V tomto případě se tedy vyplatí použít druhou verzi dotazu.

    Dotaz nad objektově relačním úložištěm

    SQL

    SELECT O.nazev, (SELECT COALESCE(SUM(N.cena), 0) FROM nakup_obj N WHERE REF(O)=N.ob_nazev) AS castka FROM obchod_obj O;

    Exekuční plán

    Plan hash value: 2248251368 --------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 5 | 160 | 2 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 19 | | | |* 2 | TABLE ACCESS FULL| NAKUP_OBJ | 2 | 38 | 2 (0)| 00:00:01 | | 3 | TABLE ACCESS FULL | OBCHOD_OBJ | 5 | 160 | 2 (0)| 00:00:01 | --------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("N"."SYS_NC00008$"=:B1) Statistics ----------------------------------------------------------- 0 recursive calls 0 db block gets 30 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 0 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    NAZEV CASTKA -------------------------------------------------- ---------------------- Dookie 14549 901 Bikes 6600 Katmar 0 Bike Kellys Seky 0 Madla Sport 18400 5 rows selected

    Diskuse 1

    Odpovídá očekávané odezvě. Pořadí řádků je rozdílné od předchozích dvou verzí.

    Diskuse 2

    Nejvýhodnější je Verze 2. Ukázalo se, že v tomto případě je výhodnější použití hodnotových cizích klíčů namísto objektových referencí.

  2. Dotaz 2

    Zobrazit všechna hodnocení obchodů a nákupy. Ke každému nákupu přiřadit všechna hodnocení vztahující se k obchodu, kde byl nákup proveden. Zobrazit i nákupy v obchodech, které nebyly hodnoceny a hodnocení obchodů, kde nebyl ještě proveden nákup.

    První verze

    SQL

    SELECT * FROM nakup FULL OUTER JOIN hodnoceni USING(ob_nazev);

    Exekuční plán

    Plan hash value: 1177690318 ---------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 14 | 4242 | 8 (13)| 00:00:01 | | 1 | VIEW | | 14 | 4242 | 8 (13)| 00:00:01 | | 2 | UNION-ALL | | | | | | |* 3 | HASH JOIN OUTER | | 12 | 852 | 5 (20)| 00:00:01 | | 4 | TABLE ACCESS FULL| NAKUP | 7 | 357 | 2 (0)| 00:00:01 | | 5 | TABLE ACCESS FULL| HODNOCENI | 7 | 140 | 2 (0)| 00:00:01 | |* 6 | HASH JOIN ANTI | | 2 | 58 | 4 (25)| 00:00:01 | | 7 | TABLE ACCESS FULL| HODNOCENI | 7 | 140 | 2 (0)| 00:00:01 | | 8 | INDEX FULL SCAN | PK_NAKUP | 7 | 63 | 1 (0)| 00:00:01 | ---------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("NAKUP"."OB_NAZEV"="HODNOCENI"."OB_NAZEV"(+)) 6 - access("NAKUP"."OB_NAZEV"="HODNOCENI"."OB_NAZEV") Statistics ----------------------------------------------------------- 1 recursive calls 0 db block gets 16 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 1 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    OB_NAZEV CENA DATUM JE_ID_JEZDCE KO_MODEL KO_VYROBCE KO_ROK_VYROBY SORTIMENT CENY PRIVETIVOST SLOVNI_HODNOCENI JE_ID_JEZDCE -------------------------------------------------- ---------------------- ------------------------- ---------------------- -------------------------------------------------- -------------------------------------------------- ------------- ---------------------- ---------------------- ---------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------- Dookie 4000 10.09.03 2 Dragstar LeaderFox 2003 2 2 1 Pohodovej majitel. 1 Dookie 450 29.03.04 1 Minion DH Maxxis 2004 2 2 1 Pohodovej majitel. 1 Dookie 10099 29.03.04 1 DirtJumper III Marzocchi 2004 2 2 1 Pohodovej majitel. 1 901 Bikes 6000 03.02.04 2 Blackhorse Blackhorse 2003 1 3 2 1 901 Bikes 600 29.03.04 1 Minion DH Maxxis 2004 1 3 2 1 Dookie 4000 10.09.03 2 Dragstar LeaderFox 2003 2 1 1 4 Dookie 450 29.03.04 1 Minion DH Maxxis 2004 2 1 1 4 Dookie 10099 29.03.04 1 DirtJumper III Marzocchi 2004 2 1 1 4 Madla Sport 400 10.09.05 3 High Roller Maxxis 2004 4 1 3 3 Madla Sport 18000 10.09.05 3 P2 Specialized 2005 4 1 3 3 Dookie 4000 10.09.03 2 Dragstar LeaderFox 2003 2 2 1 6 Dookie 450 29.03.04 1 Minion DH Maxxis 2004 2 2 1 6 Dookie 10099 29.03.04 1 DirtJumper III Marzocchi 2004 2 2 1 6 Katmar 3 3 4 3 Katmar 3 2 4 1 15 rows selected

    Diskuse 1

    Odezva je správná.

    Diskuse 2

    Nyní provedeme dotaz jinou technikou. Místo plného vnějšího spojení provedeme dvě jednostranná vnější spojení a ty potom spojíme množinovým sjednocením.

    Druhá verze

    SQL

    (SELECT * FROM nakup LEFT OUTER JOIN hodnoceni USING(ob_nazev)) UNION (SELECT * FROM nakup RIGHT OUTER JOIN hodnoceni USING(ob_nazev));

    Exekuční plán

    Plan hash value: 1670255159 ---------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 24 | 1512 | 11 (64)| 00:00:01 | | 1 | SORT UNIQUE | | 24 | 1512 | 11 (64)| 00:00:01 | | 2 | UNION-ALL | | | | | | |* 3 | HASH JOIN OUTER | | 12 | 756 | 5 (20)| 00:00:01 | | 4 | TABLE ACCESS FULL| NAKUP | 7 | 301 | 2 (0)| 00:00:01 | | 5 | TABLE ACCESS FULL| HODNOCENI | 7 | 140 | 2 (0)| 00:00:01 | |* 6 | HASH JOIN OUTER | | 12 | 756 | 5 (20)| 00:00:01 | | 7 | TABLE ACCESS FULL| HODNOCENI | 7 | 140 | 2 (0)| 00:00:01 | | 8 | TABLE ACCESS FULL| NAKUP | 7 | 301 | 2 (0)| 00:00:01 | ---------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("NAKUP"."OB_NAZEV"="HODNOCENI"."OB_NAZEV"(+)) 6 - access("HODNOCENI"."OB_NAZEV"="NAKUP"."OB_NAZEV"(+)) Statistics ----------------------------------------------------------- 1 recursive calls 0 db block gets 20 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 1 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    OB_NAZEV CENA DATUM QCSJ_C000000000300000 KO_MODEL KO_VYROBCE KO_ROK_VYROBY SORTIMENT CENY PRIVETIVOST SLOVNI_HODNOCENI QCSJ_C000000000300001 -------------------------------------------------- ---------------------- ------------------------- ---------------------- -------------------------------------------------- -------------------------------------------------- ------------- ---------------------- ---------------------- ---------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------- 901 Bikes 600 29.03.04 1 Minion DH Maxxis 2004 1 3 2 1 901 Bikes 6000 03.02.04 2 Blackhorse Blackhorse 2003 1 3 2 1 Dookie 450 29.03.04 1 Minion DH Maxxis 2004 2 1 1 4 Dookie 450 29.03.04 1 Minion DH Maxxis 2004 2 2 1 Pohodovej majitel. 1 Dookie 450 29.03.04 1 Minion DH Maxxis 2004 2 2 1 6 Dookie 4000 10.09.03 2 Dragstar LeaderFox 2003 2 1 1 4 Dookie 4000 10.09.03 2 Dragstar LeaderFox 2003 2 2 1 Pohodovej majitel. 1 Dookie 4000 10.09.03 2 Dragstar LeaderFox 2003 2 2 1 6 Dookie 10099 29.03.04 1 DirtJumper III Marzocchi 2004 2 1 1 4 Dookie 10099 29.03.04 1 DirtJumper III Marzocchi 2004 2 2 1 Pohodovej majitel. 1 Dookie 10099 29.03.04 1 DirtJumper III Marzocchi 2004 2 2 1 6 Katmar 3 2 4 1 Katmar 3 3 4 3 Madla Sport 400 10.09.05 3 High Roller Maxxis 2004 4 1 3 3 Madla Sport 18000 10.09.05 3 P2 Specialized 2005 4 1 3 3 15 rows selected

    Diskuse 1

    Výstupy se liší pořadím. V druhém případě také přibyly automaticky vytvořené sloupce.

    Diskuse 2

    Dotazy mají podobné exekuční plány. Výhodnější je první verze.

    Dotaz nad objektově relačním úložištěm

    SQL

    (SELECT COALESCE(DEREF(N.ob_nazev).nazev, DEREF(h.ob_nazev).nazev), cena, datum, DEREF(N.je_id_jezdce).id_jezdce, DEREF(N.ko_komponent).model, DEREF(N.ko_komponent).vyrobce, DEREF(N.ko_komponent).rok_vyroby, H.sortiment, h.ceny, h.privetivost, h.slovni_hodnoceni, DEREF(h.je_id_jezdce).id_jezdce FROM nakup_obj N LEFT OUTER JOIN hodnoceni_obj H ON(N.ob_nazev=h.ob_nazev)) UNION (SELECT COALESCE(DEREF(N.ob_nazev).nazev, DEREF(h.ob_nazev).nazev), cena, datum, DEREF(N.je_id_jezdce).id_jezdce, DEREF(N.ko_komponent).model, DEREF(N.ko_komponent).vyrobce, DEREF(N.ko_komponent).rok_vyroby, H.sortiment, h.ceny, h.privetivost, h.slovni_hodnoceni, DEREF(h.je_id_jezdce).id_jezdce FROM nakup_obj N RIGHT OUTER JOIN hodnoceni_obj H ON(N.ob_nazev=h.ob_nazev));

    Exekuční plán

    Plan hash value: 914798819 ------------------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1206 | 229K| 34 (59)| 00:00:01 | | 1 | SORT UNIQUE | | 1206 | 229K| 34 (59)| 00:00:01 | | 2 | UNION-ALL | | | | | | |* 3 | HASH JOIN RIGHT OUTER | | 603 | 114K| 16 (13)| 00:00:01 | | 4 | TABLE ACCESS FULL | JEZDEC_OBJ | 10 | 120 | 2 (0)| 00:00:01 | |* 5 | HASH JOIN RIGHT OUTER | | 241 | 44103 | 14 (15)| 00:00:01 | | 6 | TABLE ACCESS FULL | OBCHOD_OBJ | 5 | 100 | 2 (0)| 00:00:01 | |* 7 | HASH JOIN RIGHT OUTER | | 193 | 31459 | 11 (10)| 00:00:01 | | 8 | TABLE ACCESS FULL | HODNOCENI_OBJ | 7 | 294 | 2 (0)| 00:00:01 | |* 9 | HASH JOIN OUTER | | 110 | 13310 | 9 (12)| 00:00:01 | | 10 | NESTED LOOPS OUTER | | 33 | 3597 | 6 (0)| 00:00:01 | | 11 | NESTED LOOPS OUTER | | 12 | 936 | 4 (0)| 00:00:01 | | 12 | TABLE ACCESS FULL | NAKUP_OBJ | 7 | 406 | 2 (0)| 00:00:01 | | 13 | TABLE ACCESS BY INDEX ROWID| OBCHOD_OBJ | 2 | 40 | 1 (0)| 00:00:01 | |* 14 | INDEX UNIQUE SCAN | SYS_C001505094 | 1 | | 0 (0)| 00:00:01 | | 15 | TABLE ACCESS BY INDEX ROWID | KOMPONENT_OBJ | 3 | 93 | 1 (0)| 00:00:01 | |* 16 | INDEX UNIQUE SCAN | SYS_C001505105 | 1 | | 0 (0)| 00:00:01 | | 17 | TABLE ACCESS FULL | JEZDEC_OBJ | 10 | 120 | 2 (0)| 00:00:01 | |* 18 | HASH JOIN RIGHT OUTER | | 603 | 114K| 16 (13)| 00:00:01 | | 19 | TABLE ACCESS FULL | JEZDEC_OBJ | 10 | 120 | 2 (0)| 00:00:01 | |* 20 | HASH JOIN RIGHT OUTER | | 181 | 33123 | 14 (15)| 00:00:01 | | 21 | TABLE ACCESS FULL | KOMPONENT_OBJ | 17 | 527 | 2 (0)| 00:00:01 | |* 22 | HASH JOIN OUTER | | 64 | 9728 | 11 (10)| 00:00:01 | |* 23 | HASH JOIN OUTER | | 38 | 5016 | 9 (12)| 00:00:01 | | 24 | NESTED LOOPS OUTER | | 22 | 1628 | 6 (0)| 00:00:01 | | 25 | NESTED LOOPS OUTER | | 9 | 558 | 4 (0)| 00:00:01 | | 26 | TABLE ACCESS FULL | HODNOCENI_OBJ | 7 | 294 | 2 (0)| 00:00:01 | | 27 | TABLE ACCESS BY INDEX ROWID| OBCHOD_OBJ | 1 | 20 | 1 (0)| 00:00:01 | |* 28 | INDEX UNIQUE SCAN | SYS_C001505094 | 1 | | 0 (0)| 00:00:01 | | 29 | TABLE ACCESS BY INDEX ROWID | JEZDEC_OBJ | 3 | 36 | 1 (0)| 00:00:01 | |* 30 | INDEX UNIQUE SCAN | SYS_C001505138 | 1 | | 0 (0)| 00:00:01 | | 31 | TABLE ACCESS FULL | NAKUP_OBJ | 7 | 406 | 2 (0)| 00:00:01 | | 32 | TABLE ACCESS FULL | OBCHOD_OBJ | 5 | 100 | 2 (0)| 00:00:01 | ------------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("P000018$"."SYS_NC_OID$"(+)="H"."SYS_NC00010$") 5 - access("P000012$"."SYS_NC_OID$"(+)="H"."SYS_NC00009$") 7 - access("N"."SYS_NC00008$"="H"."SYS_NC00009$"(+)) 9 - access("P000014$"."SYS_NC_OID$"(+)="N"."SYS_NC00009$") 14 - access("P000010$"."SYS_NC_OID$"(+)="N"."SYS_NC00008$") 16 - access("P000016$"."SYS_NC_OID$"(+)="N"."SYS_NC00010$") 18 - access("P000024$"."SYS_NC_OID$"(+)="N"."SYS_NC00009$") 20 - access("P000026$"."SYS_NC_OID$"(+)="N"."SYS_NC00010$") 22 - access("P000020$"."SYS_NC_OID$"(+)="N"."SYS_NC00008$") 23 - access("N"."SYS_NC00008$"(+)="H"."SYS_NC00009$") 28 - access("P000022$"."SYS_NC_OID$"(+)="H"."SYS_NC00009$") 30 - access("P000028$"."SYS_NC_OID$"(+)="H"."SYS_NC00010$") Statistics ----------------------------------------------------------- 0 recursive calls 0 db block gets 86 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 0 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    NAZEV CENA DATUM ID_JEZDCE MODEL VYROBCE ROK_VYROBY SORTIMENT CENY PRIVETIVOST SLOVNI_HODNOCENI ID_JEZDCE -------------------------------------------------- ---------------------- ------------------------- ---------------------- -------------------------------------------------- -------------------------------------------------- ---------- ---------------------- ---------------------- ---------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------- 901 Bikes 600 29.03.04 1 Minion DH Maxxis 2004 1 3 2 1 901 Bikes 6000 03.02.04 2 Blackhorse Blackhorse 2003 1 3 2 1 Dookie 450 29.03.04 1 Minion DH Maxxis 2004 2 1 1 4 Dookie 450 29.03.04 1 Minion DH Maxxis 2004 2 2 1 Pohodovej majitel. 1 Dookie 450 29.03.04 1 Minion DH Maxxis 2004 2 2 1 6 Dookie 4000 10.09.03 2 Dragstar LeaderFox 2003 2 1 1 4 Dookie 4000 10.09.03 2 Dragstar LeaderFox 2003 2 2 1 Pohodovej majitel. 1 Dookie 4000 10.09.03 2 Dragstar LeaderFox 2003 2 2 1 6 Dookie 10099 29.03.04 1 DirtJumper III Marzocchi 2004 2 1 1 4 Dookie 10099 29.03.04 1 DirtJumper III Marzocchi 2004 2 2 1 Pohodovej majitel. 1 Dookie 10099 29.03.04 1 DirtJumper III Marzocchi 2004 2 2 1 6 Katmar 3 2 4 1 Katmar 3 3 4 3 Madla Sport 400 10.09.05 3 High Roller Maxxis 2004 4 1 3 3 Madla Sport 18000 10.09.05 3 P2 Specialized 2005 4 1 3 3 15 rows selected

    Diskuse 1

    Odpovídá očekávané odezvě. Nepodařilo se najít objektové řešení, které by se obešlo bez použití spojení. Je to z toho důvodu, že z povahy dotazu je jen malá provázanost mezi řádky z jedné a druhé tabulky. Zajímavé je, že bylo nutné použít sjednocení dvou vnějších polospojení. Pokud se zadal příkaz používající FULL OUTER JOIN došlo k chybě a byl okamžitě uzavřen socket spojení k databázi - tedy s největší pravděpodobností byl ukončen proces provádějící daný příkaz.

    Diskuse 2

    Nejvýhodnější je verze 1. Objektový přístup je v tomto případě zcela nevhodný. Je nutné totiž načíst i objekty z dalších tabulek. Při neobjektovém přístupu stačilo vypsat hodnoty cizích klíčů.

  3. Dotaz 3

    Názvy obchodů, kde byla provedena koupě i byl hodnocen.

    První verze

    SQL

    SELECT ob_nazev nazev FROM nakup INTERSECT SELECT ob_nazev nazev FROM hodnoceni;

    Exekuční plán

    Plan hash value: 620573327 ------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 7 | 119 | 4 (75)| 00:00:01 | | 1 | INTERSECTION | | | | | | | 2 | SORT UNIQUE | | 7 | 63 | 2 (50)| 00:00:01 | | 3 | INDEX FULL SCAN | PK_NAKUP | 7 | 63 | 1 (0)| 00:00:01 | | 4 | SORT UNIQUE NOSORT| | 7 | 56 | 2 (50)| 00:00:01 | | 5 | INDEX FULL SCAN | PK_HODNOCENI | 7 | 56 | 1 (0)| 00:00:01 | ------------------------------------------------------------------------------------ Statistics ----------------------------------------------------------- 0 recursive calls 0 db block gets 2 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 0 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    NAZEV -------------------------------------------------- 901 Bikes Dookie Madla Sport 3 rows selected

    Diskuse 1

    Odezva je správná. Je zřejmé, že se používá řazení.

    Diskuse 2

    Místo množinového průniku použijeme spojení a porovnáme.

    Druhá verze

    SQL

    SELECT DISTINCT ob_nazev nazev FROM hodnoceni JOIN nakup USING(ob_nazev);

    Exekuční plán

    Plan hash value: 4006305037 ---------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 3 | 51 | 4 (50)| 00:00:01 | | 1 | HASH UNIQUE | | 3 | 51 | 4 (50)| 00:00:01 | |* 2 | HASH JOIN | | 12 | 204 | 3 (34)| 00:00:01 | | 3 | INDEX FULL SCAN| PK_HODNOCENI | 7 | 56 | 1 (0)| 00:00:01 | | 4 | INDEX FULL SCAN| PK_NAKUP | 7 | 63 | 1 (0)| 00:00:01 | ---------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("HODNOCENI"."OB_NAZEV"="NAKUP"."OB_NAZEV") Statistics ----------------------------------------------------------- 1 recursive calls 0 db block gets 2 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 1 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    NAZEV -------------------------------------------------- Madla Sport Dookie 901 Bikes 3 rows selected

    Diskuse 1

    Odezva je správná. Operace hash unique se používá z důvodu uvedení klíčového slova DISTINCT.

    Diskuse 2

    Výhodnější je první přístup. Seřadit jednotlivé mezivýsledky a poté provést průnik vychází lépe než provést join a následně z něj odstraňovat duplicity.

    Dotaz nad objektově relačním úložištěm

    SQL

    SELECT DISTINCT DEREF(N.ob_nazev).nazev AS nazev FROM nakup_obj N WHERE N.ob_nazev IN (SELECT ob_nazev FROM hodnoceni_obj);

    Exekuční plán

    Plan hash value: 3286966436 ------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 5 | 415 | 8 (25)| 00:00:01 | | 1 | HASH UNIQUE | | 5 | 415 | 8 (25)| 00:00:01 | |* 2 | HASH JOIN | | 20 | 1660 | 7 (15)| 00:00:01 | | 3 | NESTED LOOPS OUTER | | 12 | 804 | 4 (0)| 00:00:01 | | 4 | TABLE ACCESS FULL | NAKUP_OBJ | 7 | 112 | 2 (0)| 00:00:01 | | 5 | TABLE ACCESS BY INDEX ROWID| OBCHOD_OBJ | 2 | 102 | 1 (0)| 00:00:01 | |* 6 | INDEX UNIQUE SCAN | SYS_C001505094 | 1 | | 0 (0)| 00:00:01 | | 7 | TABLE ACCESS FULL | HODNOCENI_OBJ | 7 | 112 | 2 (0)| 00:00:01 | ------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("N"."SYS_NC00008$"="HODNOCENI_OBJ"."SYS_NC00009$") 6 - access("P000004$"."SYS_NC_OID$"(+)="N"."SYS_NC00008$") Statistics ----------------------------------------------------------- 36 recursive calls 0 db block gets 50 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 1 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    NAZEV -------------------------------------------------- Madla Sport Dookie 901 Bikes 3 rows selected

    Diskuse 1

    Odpovídá očekávané odezvě.

    Diskuse 2

    Nejvýhodnější je první verze. Nejhorší je objektová verze. Mimo jiné vyžaduje další čtení z tabulky Obchod.

  4. Dotaz 4

    Kdyby se každý jezdec účastnil každého závodu, kolik by bylo takových účastí.

    První verze

    SQL

    SELECT COUNT(*) pocet FROM jezdec CROSS JOIN zavod;

    Exekuční plán

    Plan hash value: 3490665904 ----------------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | ----------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 4 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | MERGE JOIN CARTESIAN | | 50 | 4 (0)| 00:00:01 | | 3 | INDEX FULL SCAN | PK_ZAVOD | 5 | 1 (0)| 00:00:01 | | 4 | BUFFER SORT | | 10 | 3 (0)| 00:00:01 | | 5 | INDEX FAST FULL SCAN| PK_JEZDEC | 10 | 1 (0)| 00:00:01 | ----------------------------------------------------------------------------- Statistics ----------------------------------------------------------- 1 recursive calls 0 db block gets 4 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 1 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    POCET ---------------------- 50 1 rows selected

    Diskuse 1

    Odpovídá očekávané odezvě.

    Diskuse 2

    Zkusíme výsledek vypočítat jako násobení počtu hodnot v jednotlivých tabulkách.

    Druhá verze

    SQL

    SELECT (SELECT COUNT(*) FROM jezdec) * (SELECT COUNT(*) FROM zavod) pocet FROM dual;

    Exekuční plán

    Plan hash value: 1302054247 ------------------------------------------------------------------------ | Id | Operation | Name | Rows | Cost (%CPU)| Time | ------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | INDEX FULL SCAN | PK_JEZDEC | 10 | 1 (0)| 00:00:01 | | 3 | SORT AGGREGATE | | 1 | | | | 4 | INDEX FULL SCAN| PK_ZAVOD | 5 | 1 (0)| 00:00:01 | | 5 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | ------------------------------------------------------------------------ Statistics ----------------------------------------------------------- 0 recursive calls 0 db block gets 2 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 0 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    POCET ---------------------- 50 1 rows selected

    Diskuse 1

    Odpovídá očekávané odezvě.

    Diskuse 2

    Druhá verze je efektivnější. Není totiž třeba provádět náročný cross join, pokud nás nezajímají přímo data z něj, nýbrž jen jejich agregace.

    Dotaz nad objektově relačním úložištěm

    SQL

    SELECT (SELECT COUNT(*) FROM jezdec_obj) * (SELECT COUNT(*) FROM zavod_obj) pocet FROM dual;

    Exekuční plán

    Plan hash value: 2760921415 ----------------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | ----------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | INDEX FULL SCAN | SYS_C001505139 | 10 | 1 (0)| 00:00:01 | | 3 | SORT AGGREGATE | | 1 | | | | 4 | INDEX FULL SCAN| SYS_C001505129 | 5 | 1 (0)| 00:00:01 | | 5 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | ----------------------------------------------------------------------------- Statistics ----------------------------------------------------------- 1 recursive calls 0 db block gets 2 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 1 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    POCET ---------------------- 50 1 rows selected

    Diskuse 1

    Odpovídá očekávané odezvě.

    Diskuse 2

    Verze 2 a 3 jsou rovnocennné. Objektovost nemá na tento dotaz vliv, nevyužívají se žádné reference.

  5. Dotaz 5

    Seznam jezdců (jméno, příjmení) s počtem účastí na závodech. Zobrazit pouze jezdce, kteří se účastnili více jak jednoho závodu.

    První verze

    SQL

    SELECT jmeno, prijmeni, pocet FROM ( SELECT role10_id_jezdce id_jezdce, COUNT(*) pocet FROM se_ucastnil GROUP BY role10_id_jezdce HAVING COUNT(*)>1 ) NATURAL JOIN jezdec;

    Exekuční plán

    Plan hash value: 122544899 -------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 40 | 3 (34)| 00:00:01 | | 1 | NESTED LOOPS | | 1 | 40 | 3 (34)| 00:00:01 | | 2 | VIEW | | 1 | 26 | 2 (50)| 00:00:01 | |* 3 | FILTER | | | | | | | 4 | HASH GROUP BY | | 1 | 2 | 2 (50)| 00:00:01 | | 5 | INDEX FULL SCAN | UNQ_SE_UCASTNIL_1 | 10 | 20 | 1 (0)| 00:00:01 | | 6 | TABLE ACCESS BY INDEX ROWID| JEZDEC | 1 | 14 | 1 (0)| 00:00:01 | |* 7 | INDEX UNIQUE SCAN | PK_JEZDEC | 1 | | 0 (0)| 00:00:01 | -------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - filter(COUNT(*)>1) 7 - access("from$_subquery$_001"."ID_JEZDCE"="JEZDEC"."ID_JEZDCE") Statistics ----------------------------------------------------------- 24 recursive calls 0 db block gets 8 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 1 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    JMENO PRIJMENI POCET ------------------------------ ------------------------------ ---------------------- Marek Handlu 2 Michal Andy 5 2 rows selected

    Diskuse 1

    Odpovídá očekávané odezvě.

    Diskuse 2

    Zkusíme požadavek na minimálně počet závodů přesunout z vnitřku ven, tedy použijeme WHERE místo HAVING.

    Druhá verze

    SQL

    SELECT jmeno, prijmeni, pocet FROM ( SELECT role10_id_jezdce id_jezdce, COUNT(*) pocet FROM se_ucastnil GROUP BY role10_id_jezdce ) NATURAL JOIN jezdec WHERE pocet > 1;

    Exekuční plán

    Plan hash value: 122544899 -------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 40 | 3 (34)| 00:00:01 | | 1 | NESTED LOOPS | | 1 | 40 | 3 (34)| 00:00:01 | | 2 | VIEW | | 1 | 26 | 2 (50)| 00:00:01 | |* 3 | FILTER | | | | | | | 4 | HASH GROUP BY | | 1 | 2 | 2 (50)| 00:00:01 | | 5 | INDEX FULL SCAN | UNQ_SE_UCASTNIL_1 | 10 | 20 | 1 (0)| 00:00:01 | | 6 | TABLE ACCESS BY INDEX ROWID| JEZDEC | 1 | 14 | 1 (0)| 00:00:01 | |* 7 | INDEX UNIQUE SCAN | PK_JEZDEC | 1 | | 0 (0)| 00:00:01 | -------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - filter(COUNT(*)>1) 7 - access("from$_subquery$_001"."ID_JEZDCE"="JEZDEC"."ID_JEZDCE") Statistics ----------------------------------------------------------- 1 recursive calls 0 db block gets 5 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 1 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    JMENO PRIJMENI POCET ------------------------------ ------------------------------ ---------------------- Marek Handlu 2 Michal Andy 5 2 rows selected

    Diskuse 1

    Výsledek je stejný.

    Diskuse 2

    Oba dotazy mají shodné exekuční plány. Přesun podmínky se neprojevil.

    Dotaz nad objektově relačním úložištěm

    SQL

    SELECT S.role10_id_jezdce.jmeno AS jmeno, S.role10_id_jezdce.prijmeni AS prijmeni, COUNT(*) as pocet FROM se_ucastnil_obj S GROUP BY s.role10_id_jezdce.jmeno, s.role10_id_jezdce.prijmeni HAVING COUNT(*) > 1; -- alias pocet tady nefunguje

    Exekuční plán

    Plan hash value: 1599958322 -------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 38 | 5 (20)| 00:00:01 | |* 1 | FILTER | | | | | | | 2 | HASH GROUP BY | | 1 | 38 | 5 (20)| 00:00:01 | | 3 | NESTED LOOPS OUTER | | 20 | 760 | 4 (0)| 00:00:01 | | 4 | TABLE ACCESS FULL | SE_UCASTNIL_OBJ | 10 | 160 | 2 (0)| 00:00:01 | | 5 | TABLE ACCESS BY INDEX ROWID| JEZDEC_OBJ | 2 | 44 | 1 (0)| 00:00:01 | |* 6 | INDEX UNIQUE SCAN | SYS_C001505138 | 1 | | 0 (0)| 00:00:01 | -------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter(COUNT(*)>1) 6 - access("P000003$"."SYS_NC_OID$"(+)="S"."ROLE10_ID_JEZDCE") Statistics ----------------------------------------------------------- 0 recursive calls 0 db block gets 17 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 0 parse count (hard) 0 parse count (failures) Statistics ----------------------------------------------------------- 0 recursive calls 0 db block gets 0 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 0 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    JMENO PRIJMENI POCET ------------------------------ ------------------------------ ---------------------- Michal Andy 5 Marek Handlu 2 2 rows selected

    Diskuse 1

    Odpovídá očekávané odezvě. Zajímavé je, že bylo nutné použít tečkové notace místo funkce DEREF. Při použití DEREF docházelo k vrácení nesprávných údajů - součty správně ale jména špatně.

    Diskuse 2

    Neobjektové formy dotazů jsou efektivnější, ale objektový dotaz je srozumitelnější.

  6. Dotaz 6

    --DOTAZ UPRAVEN OPROTI PŘEDCHOZÍ VERZI--

    Jména jezdců, kteří mají všechny disciplíny uvedené jako oblíbené. Pro potřeby SQL je nutné převézt obecný kvantifikátor na existenční. Tedy např: Jména jezdců, pro které neexistuje disciplína, kterou by neměli rádi. Nebo ještě složitějí díky vícenásobné negaci v českých větách: Jména jezdců, pro něž žádná disciplína v systému není neoblíbená.

    První verze

    SQL

    SELECT (J.jmeno || ' ' || J.prijmeni) AS cele_jmeno FROM jezdec J WHERE NOT EXISTS (SELECT nazev FROM disciplina D MINUS SELECT M.role6_nazev AS nazev FROM ma_rad M WHERE M.role3_id_jezdce = J.id_jezdce);

    Exekuční plán

    Plan hash value: 110028514 -------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 9 | 126 | 22 (46)| 00:00:01 | |* 1 | FILTER | | | | | | | 2 | TABLE ACCESS FULL | JEZDEC | 10 | 140 | 2 (0)| 00:00:01 | | 3 | MINUS | | | | | | | 4 | SORT UNIQUE NOSORT| | 10 | 50 | 2 (50)| 00:00:01 | | 5 | INDEX FULL SCAN | PK_DISCIPLINA | 10 | 50 | 1 (0)| 00:00:01 | | 6 | SORT UNIQUE NOSORT| | 2 | 12 | 2 (50)| 00:00:01 | |* 7 | INDEX FULL SCAN | UNQ_MA_RAD_1 | 2 | 12 | 1 (0)| 00:00:01 | -------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter( NOT EXISTS ( (SELECT /*+ */ "NAZEV" FROM "DISCIPLINA" "D")MINUS (SELECT /*+ */ "M"."ROLE6_NAZEV" FROM "MA_RAD" "M" WHERE "M"."ROLE3_ID_JEZDCE"=:B1))) 7 - access("M"."ROLE3_ID_JEZDCE"=:B1) filter("M"."ROLE3_ID_JEZDCE"=:B1) Statistics ----------------------------------------------------------- 0 recursive calls 0 db block gets 25 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 0 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    CELE_JMENO ------------------------------------------------------------- Jan Schusti 1 rows selected

    Diskuse 1

    Odpovídá očekávané odezvě.

    Diskuse 2

    Místo operátoru NOT EXIST zkusíme použít agregační funkce k určení počtu disciplín, které má jezdec rád a to porovnáme s celkovým počtem disciplín v systému.

    Druhá verze

    SQL

    SELECT (J.jmeno || ' ' || J.prijmeni) AS cele_jmeno FROM jezdec J WHERE (SELECT COUNT(DISTINCT(M.role6_nazev)) FROM ma_rad M WHERE M.role3_id_jezdce=J.id_jezdce) = (SELECT COUNT(*) FROM disciplina);

    Exekuční plán

    Plan hash value: 1749947326 ------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 10 | 140 | 3 (0)| 00:00:01 | |* 1 | FILTER | | | | | | | 2 | TABLE ACCESS FULL | JEZDEC | 10 | 140 | 2 (0)| 00:00:01 | | 3 | SORT GROUP BY | | 1 | 6 | | | |* 4 | INDEX FULL SCAN | UNQ_MA_RAD_1 | 2 | 12 | 1 (0)| 00:00:01 | | 5 | SORT AGGREGATE | | 1 | | | | | 6 | INDEX FULL SCAN| PK_DISCIPLINA | 10 | | 1 (0)| 00:00:01 | ------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter( (SELECT COUNT(DISTINCT "M"."ROLE6_NAZEV") FROM "MA_RAD" "M" WHERE "M"."ROLE3_ID_JEZDCE"=:B1)= (SELECT COUNT(*) FROM "DISCIPLINA" "DISCIPLINA")) 4 - access("M"."ROLE3_ID_JEZDCE"=:B1) filter("M"."ROLE3_ID_JEZDCE"=:B1) Statistics ----------------------------------------------------------- 1 recursive calls 0 db block gets 8 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 1 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    CELE_JMENO ------------------------------------------------------------- Jan Schusti 1 rows selected

    Diskuse 1

    Odpovídá očekávané odezvě.

    Diskuse 2

    Druhá verze je značně efektivnější. V první verzi se ve WHERE části hlavního dotazu provádějí SELECTY, které vracejí data, a s těmi se navíc poté pracuje množinově, což vyžaduje jejich řazení. V druhé verzi se použije agregační funkce součtu, což je rychlejší.

    Dotaz nad objektově relačním úložištěm

    SQL

    SELECT (J.jmeno || ' ' || J.prijmeni) AS cele_jmeno FROM jezdec_obj J WHERE (SELECT COUNT(DISTINCT(role6_nazev)) FROM ma_rad_obj M WHERE M.role3_id_jezdce=REF(J)) = (SELECT COUNT(*) FROM disciplina_obj);

    Exekuční plán

    Plan hash value: 1275115247 -------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 10 | 340 | 4 (0)| 00:00:01 | |* 1 | FILTER | | | | | | | 2 | TABLE ACCESS FULL | JEZDEC_OBJ | 10 | 340 | 2 (0)| 00:00:01 | | 3 | SORT GROUP BY | | 1 | 32 | | | |* 4 | TABLE ACCESS FULL| MA_RAD_OBJ | 2 | 64 | 2 (0)| 00:00:01 | | 5 | SORT AGGREGATE | | 1 | | | | | 6 | INDEX FULL SCAN| SYS_C001505148 | 10 | | 1 (0)| 00:00:01 | -------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter( (SELECT COUNT(DISTINCT "ROLE6_NAZEV") FROM "MA_RAD_OBJ" "M" WHERE "M"."SYS_NC00005$"=:B1)= (SELECT COUNT(*) FROM "DISCIPLINA_OBJ" "DISCIPLINA_OBJ")) 4 - filter("M"."SYS_NC00005$"=:B1) Statistics ----------------------------------------------------------- 15 recursive calls 0 db block gets 60 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 1 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    CELE_JMENO ------------------------------------------------------------- Jan Schusti 1 rows selected

    Diskuse 1

    Odpovídá očekávané odezvě.

    Diskuse 2

    Nejvýhodnější je verze 2. Objektová verze je jen o malinko horší.

  7. Dotaz 7

    Názvy a případně www adresy obchodů, kde provedl jezdec s přezdívkou Mareen alespoň jeden nákup.

    První verze

    SQL

    SELECT nazev, www FROM obchod WHERE EXISTS (SELECT * FROM nakup JOIN jezdec ON(je_id_jezdce=id_jezdce) WHERE prezdivka='Mareen' AND ob_nazev=nazev);

    Exekuční plán

    Plan hash value: 675024332 --------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 2 | 84 | 6 (17)| 00:00:01 | |* 1 | HASH JOIN SEMI | | 2 | 84 | 6 (17)| 00:00:01 | | 2 | TABLE ACCESS FULL | OBCHOD | 5 | 75 | 2 (0)| 00:00:01 | | 3 | VIEW | VW_SQ_1 | 2 | 54 | 3 (0)| 00:00:01 | | 4 | NESTED LOOPS | | 2 | 40 | 3 (0)| 00:00:01 | |* 5 | TABLE ACCESS FULL| JEZDEC | 1 | 9 | 2 (0)| 00:00:01 | |* 6 | INDEX FULL SCAN | PK_NAKUP | 2 | 22 | 1 (0)| 00:00:01 | --------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("OB_NAZEV"="NAZEV") 5 - filter("JEZDEC"."PREZDIVKA"='Mareen') 6 - access("JE_ID_JEZDCE"="ID_JEZDCE") filter("JE_ID_JEZDCE"="ID_JEZDCE") Statistics ----------------------------------------------------------- 1 recursive calls 0 db block gets 11 consistent gets 4 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 1 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    NAZEV WWW -------------------------------------------------- ---------------------------------------------------------------------------------------------------- 901 Bikes Dookie www.dookie.cz 2 rows selected

    Diskuse 1

    Odpovídá očekávané odezvě.

    Diskuse 2

    Operátor EXISTS nahradíme operátorem IN. Místo joinu použijeme podmínku v klauzuli WHERE.

    Druhá verze

    SQL

    SELECT nazev, www FROM obchod WHERE nazev IN ( SELECT ob_nazev FROM nakup WHERE je_id_jezdce=(SELECT id_jezdce FROM jezdec WHERE prezdivka='Mareen') );

    Exekuční plán

    Plan hash value: 3226301129 --------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 2 | 84 | 6 (17)| 00:00:01 | |* 1 | HASH JOIN SEMI | | 2 | 84 | 6 (17)| 00:00:01 | | 2 | TABLE ACCESS FULL | OBCHOD | 5 | 75 | 2 (0)| 00:00:01 | | 3 | VIEW | VW_NSO_1 | 2 | 54 | 3 (0)| 00:00:01 | |* 4 | INDEX FULL SCAN | PK_NAKUP | 2 | 22 | 1 (0)| 00:00:01 | |* 5 | TABLE ACCESS FULL| JEZDEC | 1 | 9 | 2 (0)| 00:00:01 | --------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("NAZEV"="$nso_col_1") 4 - access("JE_ID_JEZDCE"= (SELECT "ID_JEZDCE" FROM "JEZDEC" "JEZDEC" WHERE "PREZDIVKA"='Mareen')) filter("JE_ID_JEZDCE"= (SELECT "ID_JEZDCE" FROM "JEZDEC" "JEZDEC" WHERE "PREZDIVKA"='Mareen')) 5 - filter("PREZDIVKA"='Mareen') Statistics ----------------------------------------------------------- 1 recursive calls 0 db block gets 11 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 1 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    NAZEV WWW -------------------------------------------------- ---------------------------------------------------------------------------------------------------- 901 Bikes Dookie www.dookie.cz 2 rows selected

    Diskuse 1

    Odpovídá očekávané odezvě.

    Diskuse 2

    Druhá verze je efektivnější. V první verzi se používá nested loops kvůli spojování.

    Dotaz nad objektově relačním úložištěm

    SQL

    SELECT DISTINCT DEREF(ob_nazev).nazev AS nazev, DEREF(ob_nazev).www AS www FROM nakup_obj N WHERE DEREF(je_id_jezdce).prezdivka = 'Mareen';

    Exekuční plán

    Plan hash value: 3882746863 -------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 8 | 592 | 8 (25)| 00:00:01 | | 1 | HASH UNIQUE | | 8 | 592 | 8 (25)| 00:00:01 | |* 2 | FILTER | | | | | | |* 3 | HASH JOIN OUTER | | 39 | 2886 | 7 (15)| 00:00:01 | | 4 | NESTED LOOPS OUTER | | 12 | 684 | 4 (0)| 00:00:01 | | 5 | TABLE ACCESS FULL | NAKUP_OBJ | 7 | 224 | 2 (0)| 00:00:01 | | 6 | TABLE ACCESS BY INDEX ROWID| OBCHOD_OBJ | 2 | 50 | 1 (0)| 00:00:01 | |* 7 | INDEX UNIQUE SCAN | SYS_C001505094 | 1 | | 0 (0)| 00:00:01 | | 8 | TABLE ACCESS FULL | JEZDEC_OBJ | 10 | 170 | 2 (0)| 00:00:01 | -------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter(DECODE("P000005$"."SYS_NC_OID$",NULL,SYS_OP_ATG(NULL,4,5,2),"P000005$"."PREZ DIVKA")='Mareen') 3 - access("P000005$"."SYS_NC_OID$"(+)="N"."SYS_NC00009$") 7 - access("P000003$"."SYS_NC_OID$"(+)="N"."SYS_NC00008$") Statistics ----------------------------------------------------------- 22 recursive calls 0 db block gets 64 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 1 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    NAZEV WWW -------------------------------------------------- ---------------------------------------------------------------------------------------------------- Dookie www.dookie.cz 901 Bikes 2 rows selected

    Diskuse 1

    Odpovídá očekávané odezvě.

    Diskuse 2

    Nejvýhodnější je verze 2. Objektová verze je opět méně efektivní, ale její zápis je o něco srozumitelnější.

  8. Dotaz 8

    Jména a příjmení jezdců, kteří se ještě nezúčastnili žádného závodu.

    První verze

    SQL

    SELECT jmeno, prijmeni FROM jezdec WHERE id_jezdce NOT IN (SELECT role10_id_jezdce FROM se_ucastnil);

    Exekuční plán

    Plan hash value: 260798367 ---------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 5 | 80 | 4 (25)| 00:00:01 | |* 1 | HASH JOIN ANTI | | 5 | 80 | 4 (25)| 00:00:01 | | 2 | TABLE ACCESS FULL| JEZDEC | 10 | 140 | 2 (0)| 00:00:01 | | 3 | INDEX FULL SCAN | UNQ_SE_UCASTNIL_1 | 10 | 20 | 1 (0)| 00:00:01 | ---------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("ID_JEZDCE"="ROLE10_ID_JEZDCE") Statistics ----------------------------------------------------------- 0 recursive calls 0 db block gets 6 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 0 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    JMENO PRIJMENI ------------------------------ ------------------------------ Tomáš Andy Martin Holý Jakub Růža Štěpán Grundl Michal Benest 5 rows selected

    Diskuse 1

    Odpovídá očekávané odezvě.

    Diskuse 2

    Porovnáme jestli se operátory NOT IN a NOT EXISTS liší.

    Druhá verze

    SQL

    SELECT jmeno, prijmeni FROM jezdec WHERE NOT EXISTS (SELECT * FROM se_ucastnil WHERE id_jezdce= role10_id_jezdce);

    Exekuční plán

    Plan hash value: 260798367 ---------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 5 | 80 | 4 (25)| 00:00:01 | |* 1 | HASH JOIN ANTI | | 5 | 80 | 4 (25)| 00:00:01 | | 2 | TABLE ACCESS FULL| JEZDEC | 10 | 140 | 2 (0)| 00:00:01 | | 3 | INDEX FULL SCAN | UNQ_SE_UCASTNIL_1 | 10 | 20 | 1 (0)| 00:00:01 | ---------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("ID_JEZDCE"="ROLE10_ID_JEZDCE") Statistics ----------------------------------------------------------- 1 recursive calls 0 db block gets 6 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 1 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    JMENO PRIJMENI ------------------------------ ------------------------------ Tomáš Andy Martin Holý Jakub Růža Štěpán Grundl Michal Benest 5 rows selected

    Diskuse 1

    Výsledek je stejný.

    Diskuse 2

    Je zřejmé, že NOT IN a NOT EXISTS mají stejný exekuční plán.

    Dotaz nad objektově relačním úložištěm

    SQL

    SELECT J.jmeno, J.prijmeni FROM jezdec_obj J WHERE REF(J) NOT IN (SELECT role10_id_jezdce FROM se_ucastnil_obj);

    Exekuční plán

    Plan hash value: 2351109479 -------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 34 | 4 (0)| 00:00:01 | |* 1 | FILTER | | | | | | | 2 | TABLE ACCESS FULL| JEZDEC_OBJ | 10 | 340 | 2 (0)| 00:00:01 | |* 3 | TABLE ACCESS FULL| SE_UCASTNIL_OBJ | 2 | 32 | 2 (0)| 00:00:01 | -------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter( NOT EXISTS (SELECT /*+ */ 0 FROM "SE_UCASTNIL_OBJ" "SE_UCASTNIL_OBJ" WHERE LNNVL("SE_UCASTNIL_OBJ"."SYS_NC00006$"<>:B1))) 3 - filter(LNNVL("SE_UCASTNIL_OBJ"."SYS_NC00006$"<>:B1)) Statistics ----------------------------------------------------------- 15 recursive calls 0 db block gets 60 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 1 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    JMENO PRIJMENI ------------------------------ ------------------------------ Tomáš Andy Jakub Růža Štěpán Grundl Michal Benest Martin Holý 5 rows selected

    Diskuse 1

    Odpovídá očekávané odezvě.

    Diskuse 2

    Všechny verze dotazu jsou ekvivalentní, co se efektivity týče.

  9. Dotaz 9

    Jména a příjmení všech registrovaných jezdců.

    První verze

    SQL

    SELECT jmeno, prijmeni FROM jezdec;

    Exekuční plán

    Plan hash value: 4067037959 ---------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 10 | 120 | 2 (0)| 00:00:01 | | 1 | TABLE ACCESS FULL| JEZDEC | 10 | 120 | 2 (0)| 00:00:01 | ---------------------------------------------------------------------------- Statistics ----------------------------------------------------------- 1 recursive calls 0 db block gets 5 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 1 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    JMENO PRIJMENI ------------------------------ ------------------------------ Marek Handlu Michal Andy Jan Schusti Jakub Anton Tomáš Andy Jakub Růža Štěpán Grundl Pavel Herink Michal Benest Martin Holý 10 rows selected

    Diskuse 1

    Odpovídá očekávané odezvě.

    Diskuse 2

    Zkusíme přidat řazení podle primárního klíče.

    Druhá verze

    SQL

    SELECT jmeno, prijmeni FROM jezdec ORDER BY id_jezdce;

    Exekuční plán

    Plan hash value: 2482864222 ----------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ----------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 10 | 140 | 2 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| JEZDEC | 10 | 140 | 2 (0)| 00:00:01 | | 2 | INDEX FULL SCAN | PK_JEZDEC | 10 | | 1 (0)| 00:00:01 | ----------------------------------------------------------------------------------------- Statistics ----------------------------------------------------------- 1 recursive calls 0 db block gets 2 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 1 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    JMENO PRIJMENI ------------------------------ ------------------------------ Marek Handlu Michal Andy Jan Schusti Jakub Anton Tomáš Andy Jakub Růža Štěpán Grundl Pavel Herink Michal Benest Martin Holý 10 rows selected

    Diskuse 1

    Výsledek je stejný včetně pořadí.

    Diskuse 2

    První verze je efektivnější. V druhém případě se navíc provádí řazení, které ale v tomto případě nemá na pořadí vliv.

    Dotaz nad objektově relačním úložištěm

    SQL

    SELECT jmeno, prijmeni FROM jezdec_obj;

    Exekuční plán

    Plan hash value: 1770270476 -------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 10 | 120 | 2 (0)| 00:00:01 | | 1 | TABLE ACCESS FULL| JEZDEC_OBJ | 10 | 120 | 2 (0)| 00:00:01 | -------------------------------------------------------------------------------- Statistics ----------------------------------------------------------- 1 recursive calls 0 db block gets 5 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 1 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    JMENO PRIJMENI ------------------------------ ------------------------------ Marek Handlu Michal Andy Jan Schusti Jakub Anton Tomáš Andy Jakub Růža Štěpán Grundl Pavel Herink Michal Benest Martin Holý 10 rows selected

    Diskuse 1

    Odpovídá očekávané odezvě.

    Diskuse 2

    Objektovost se v tomto dotazu nijak neprojevuje, jelikož se nevyužívají reference. Verze 1 a 3 jsou tedy stejně efektivní.

  10. Dotaz 10

    Jména a příjmení všech jezdců, kteří mají jako svou oblíbenou disciplínu sjezd (DH).

    První verze

    SQL

    SELECT jmeno, prijmeni FROM jezdec JOIN ma_rad ON(id_jezdce=role3_id_jezdce) WHERE role6_nazev='DH';

    Exekuční plán

    Plan hash value: 656974699 ----------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ----------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 2 | 40 | 2 (0)| 00:00:01 | | 1 | NESTED LOOPS | | 2 | 40 | 2 (0)| 00:00:01 | | 2 | TABLE ACCESS FULL| JEZDEC | 10 | 140 | 2 (0)| 00:00:01 | |* 3 | INDEX UNIQUE SCAN| UNQ_MA_RAD_1 | 1 | 6 | 0 (0)| 00:00:01 | ----------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("MA_RAD"."ROLE6_NAZEV"='DH' AND "ROLE3_ID_JEZDCE"="ID_JEZDCE") Statistics ----------------------------------------------------------- 0 recursive calls 0 db block gets 7 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 0 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    JMENO PRIJMENI ------------------------------ ------------------------------ Michal Andy Jan Schusti Jakub Anton Pavel Herink 4 rows selected

    Diskuse 1

    Odpovídá očekávané odezvě.

    Diskuse 2

    Zjistíme, jestli se JOIN chová stejně jako EXISTS.

    Druhá verze

    SQL

    SELECT jmeno, prijmeni FROM jezdec WHERE EXISTS (SELECT * FROM ma_rad WHERE role6_nazev='DH' AND id_jezdce=role3_id_jezdce);

    Exekuční plán

    Plan hash value: 379750019 ----------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ----------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 3 | 60 | 2 (0)| 00:00:01 | | 1 | NESTED LOOPS SEMI | | 3 | 60 | 2 (0)| 00:00:01 | | 2 | TABLE ACCESS FULL| JEZDEC | 10 | 140 | 2 (0)| 00:00:01 | |* 3 | INDEX UNIQUE SCAN| UNQ_MA_RAD_1 | 1 | 6 | 0 (0)| 00:00:01 | ----------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("ROLE6_NAZEV"='DH' AND "ID_JEZDCE"="ROLE3_ID_JEZDCE") Statistics ----------------------------------------------------------- 1 recursive calls 0 db block gets 7 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 1 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    JMENO PRIJMENI ------------------------------ ------------------------------ Michal Andy Jan Schusti Jakub Anton Pavel Herink 4 rows selected

    Diskuse 1

    Výsledek je stejný.

    Diskuse 2

    Obě verze mají stejné exekuční plány.

    Dotaz nad objektově relačním úložištěm

    SQL

    SELECT DEREF(role3_id_jezdce).jmeno AS jmeno, DEREF(role3_id_jezdce).prijmeni AS prijmeni FROM ma_rad_obj WHERE DEREF(role6_nazev).nazev = 'DH';

    Exekuční plán

    Plan hash value: 2605581212 ------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 24 | 1656 | 7 (0)| 00:00:01 | | 1 | NESTED LOOPS OUTER | | 24 | 1656 | 7 (0)| 00:00:01 | |* 2 | FILTER | | | | | | | 3 | NESTED LOOPS OUTER | | 24 | 1128 | 4 (0)| 00:00:01 | | 4 | TABLE ACCESS FULL | MA_RAD_OBJ | 24 | 768 | 2 (0)| 00:00:01 | | 5 | TABLE ACCESS BY INDEX ROWID| DISCIPLINA_OBJ | 1 | 15 | 1 (0)| 00:00:01 | |* 6 | INDEX UNIQUE SCAN | SYS_C001505147 | 1 | | 0 (0)| 00:00:01 | | 7 | TABLE ACCESS BY INDEX ROWID | JEZDEC_OBJ | 1 | 22 | 1 (0)| 00:00:01 | |* 8 | INDEX UNIQUE SCAN | SYS_C001505138 | 1 | | 0 (0)| 00:00:01 | ------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter(DECODE("P000005$"."SYS_NC_OID$",NULL,SYS_OP_ATG(NULL,2,3,2),"P000005$"."NAZ EV")='DH') 6 - access("P000005$"."SYS_NC_OID$"(+)="MA_RAD_OBJ"."SYS_NC00006$") 8 - access("P000003$"."SYS_NC_OID$"(+)="MA_RAD_OBJ"."SYS_NC00005$") Statistics ----------------------------------------------------------- 15 recursive calls 0 db block gets 74 consistent gets 0 physical reads 0 redo size 0 total read fandles 0 read fandles in use 0 fandle allocation failures 1 parse count (hard) 0 parse count (failures)

    Výsledek dotazu

    JMENO PRIJMENI ------------------------------ ------------------------------ Michal Andy Jan Schusti Jakub Anton Pavel Herink 4 rows selected

    Diskuse 1

    Odpovídá očekávané odezvě.

    Diskuse 2

    Neobjektové verze jsou efektivnější. Objektový přístup je snadno čitelný, ale méně efektivní při provádění, jelikož se načítají hodnoty z tabulek, na které ukazují reference.

Tabulka pokrytí dotazů

Kategorie Pokryta příkazy číslo: Charakteristika kategorie příkazu
A9jednoduché dotazy (SELECT ... FROM ... WHERE)
B3, 6, 7, 10Vyber ty, pro něž platí, že...
C8Vyber ty, pro něž NEplatí, že...
D6Vyber ty, pro něž platí, že všechny...
E6Vyber ty, pro něž platí, že žádné...
F1, 2, 4, 5, 7, 10spojení
G6, 7, 8, 10IN a EXISTS
H1, 7, 8, 10vztažený poddotaz
I3, 6, 7, 8, 10poddotaz ve WHERE
J5poddotaz ve FROM
K1, 4poddotaz v SELECT
L1, 2jednostranné vnější spojení, plné vnější spojení
M2množinové sjednocení
N6množinový rozdíl
O3množinový průnik
P1, 4, 5, 6agregační výpočty
Q1, 5seskupení a agregace
S5všechny přípustné klauzule

Procedurální rozšíření

  1. Modul - Celková suma nákupů

    U každého jezdce budeme udržovat částku, kterou utratil za komponenty. Hodnota bude součtem všech nákupů jezdce, které budou v systému. Částka se bude ukládat jako atribut jezdce a její hodnota bude aktualizována pomocí triggeru.

    Součástí modulu je i procedura, která přidá sloupec kam se částka ukládá, pokud ještě v tabulce jezdců neexistuje a spočte prvotní hodnoty součtu pro všechny jezdce.

    Dále je tu procedura pro jednodušší vložení nového pláště - vkládá automaticky do tabulky komponent i plast.

    Zdrojový text modulu

    Script

    Test

    Script s testem

    -- přidám nákup komponentu s nulovou cenou a zkontroluji korektní naplnění nového sloupce -- vymažu předchozí nákup -- přidám nákup komponentu s nenulovou cenou -- upravím nákup zvýšením ceny -- vymažu předchozí nákup

    Záznam o proběhlém testu (log):

    Odezva na provedení testu

    Diskuse výsledku testu

    -- přidám nákup komponentu s nulovou cenou a zkontroluji korektní naplnění nového sloupce konstatuji, ze krok testu prokázal předem očekavané chování -- vymažu předchozí nákup konstatuji, ze krok testu prokázal předem očekavané chování -- přidám nákup komponentu s nenulovou cenou konstatuji, ze krok testu prokázal předem očekavané chování -- upravím nákup zvýšením ceny konstatuji, ze krok testu prokázal předem očekavané chování -- vymažu předchozí nákup konstatuji, ze krok testu prokázal předem očekavané chování

    Závěr z testování

    Vše funguje tak, jak má. Na začátku se vytvoří nový sloupec celkova_castka v tabulce jezdec a naplní se správnými daty. Poté trigger hlídá operace nad tabulkou s nákupy a udržuje hodnotu celkova_castka aktuální.

    Bohužel se nepodařilo vytvořit původně zamýšlené řešení vytváření nového sloupce. Myšlenkou bylo vytvoření session triggeru, který by před každou úpravou nad tabulkou nákup zkontroloval, jestli existuje sloupec celkova_castka. Při jeho neexistenci by ho vytvořil a naplnil daty. Jelikož po DDL příkazech následuje automaticky commit, bylo nutné použít autonomní transakci. Bohužel ani poté to nefungovalo, jelikož docházelo ke kolizi v přístupu k blokovanému prostředku.

  2. Modul - Poloměry plášťů

    Je nutné zajistit, že poloměry plášťů, které jezdec využívá odpovídají poloměrům, pro které jsou určeny vidlice a rámy používané jezdcem. Tedy pokud jezdec používá vidlici pro poloměr 26", pak musí také používat plášť s poloměrem 26". Obdobně pro rám. Naopak platí, že nemůže používat plášť, který nepasuje do žádné používané vidlice a do žádného používaného rámu. Kontrolu je třeba provádět při přidávání, odebírání a upravovaní komponentů.

    Modul vyžaduje proceduru pro vkládání nového pláště z předchozího modulu. Pro jednoduchost sem byla zkopírována.

    Zdrojový text modulu

    Script

    Test

    Script s testem

    -- jezdec má rám pro 26" a vidlici pro 26", zkusím mu přidat plášť 24" -- jezdec má rám pro 26" a vidlici pro 26", zkusím mu přidat plášť 26" -- jezdec má rám pro 26" a vidlici pro 24", zkusím mu přidat plášť 24" -- jezdec má rám pro 26" a vidlici pro 24", zkusím mu přidat plášť 27" -- jezdec má rám pro 24" a vidlici pro 26", zkusím mu přidat plášť 24"

    Záznam o proběhlém testu (log):

    Odezva na provedení testu

    Diskuse výsledku testu

    -- jezdec má rám pro 26" a vidlici pro 26", zkusím mu přidat plášť 24" konstatuji, ze krok testu prokázal předem očekavané chování (zahlášení chyby) -- jezdec má rám pro 26" a vidlici pro 26", zkusím mu přidat plášť 26" konstatuji, ze krok testu prokázal předem očekavané chování (korektní vložení) -- jezdec má rám pro 26" a vidlici pro 24", zkusím mu přidat plášť 24" konstatuji, ze krok testu prokázal předem očekavané chování (korektní vložení) -- jezdec má rám pro 26" a vidlici pro 24", zkusím mu přidat plášť 27" konstatuji, ze krok testu prokázal předem očekavané chování (zahlášení chyby) -- jezdec má rám pro 24" a vidlici pro 26", zkusím mu přidat plášť 24" konstatuji, ze krok testu prokázal předem očekavané chování (korektní vložení)

    Závěr z testování

    Trigger funguje tak, jak má. Zajistí, že jezdec používá pouze pláště, které pasují do rámu a vidlic, která sám používá.

  3. Modul - Závod jen v oblíbené disciplíně

    Při vkládání informace o účasti na závodu je nutno zajistit, že se jezdec může účastnit pouze závodů v disciplíně, kterou má uvedenu jako oblíbenou.

    Zdrojový text modulu

    Script

    Test

    Script s testem

    -- zkusím přidat účast jezdce na závodu v disciplíně, kterou nemá rád -- přídám účast jezdce v disciplíně, kterou má rád

    Záznam o proběhlém testu (log):

    Odezva na provedení testu

    Diskuse výsledku testu

    -- zkusím přidat účast jezdce na závodu v disciplíně, kterou nemá rád konstatuji, ze krok testu prokázal předem očekavané chování (zahlášení chyby) -- přídám účast jezdce v disciplíně, kterou má rád konstatuji, ze krok testu prokázal předem očekavané chování (korektní vložení)

    Závěr z testování

    Trigger funguje tak, jak má. Dovolí přidat účast na závodu pouze v oblíbených disciplínách jezdců.

  4. Modul - Platný rok nákupu

    Při zaznamenávání nákupu komponentu se kontroluje, zda je rok z datumu nákupu vyšší nebo roven roku uvedení komponentu na trh.

    Zdrojový text modulu

    Script

    Test

    Script s testem

    -- zkusím přidat záznam o koupi komponentu z roku 2002 provedené v roce 2001 -- přidám záznam o koupi komponentu z roku 2002 provedené v roce 2002

    Záznam o proběhlém testu (log):

    Odezva na provedení testu

    Diskuse výsledku testu

    -- zkusím přidat záznam o koupi komponentu z roku 2002 provedené v roce 2001 konstatuji, ze krok testu prokázal předem očekavané chování (zahlášení chyby) -- přidám záznam o koupi komponentu z roku 2002 provedené v roce 2002 konstatuji, ze krok testu prokázal předem očekavané chování (korektní vložení)

    Závěr z testování

    Trigger funguje tak, jak má. Zamezí vložení nesmyslného nákupu výrobku, který ještě nebyl uveden na trh.

  5. Modul - Formát emailové adresy

    Při vkládání nového jezdce nebo při úpravách existujícího se kontroluje email, zda má platný formát emailové adresy. Trigger nejprve odstraní mezery ze začátku a konce vstupních dat a poté provede kontrolu adresy vůči regulárnímu výrazu.

    Zdrojový text modulu

    Script

    Test

    Script s testem

    - zkusím přidat jezdce s neplatnou emailovou adresou - přidám jezdce s platnou emailovou adresou

    Záznam o proběhlém testu (log):

    Odezva na provedení testu

    Diskuse výsledku testu

    - zkusím přidat jezdce s neplatnou emailovou adresou konstatuji, ze krok testu prokázal předem očekavané chování (zahlášení chyby) -- přidám jezdce s platnou emailovou adresou onstatuji, ze krok testu prokázal předem očekavané chování (korektní vložení)

    Závěr z testování

    Trigger funguje tak, jak má. Povolí vložení pouze platné emailové adresy. Ke kontrole se používá regulární výraz pokrývající všechny běžně používané emailové adresy.

  6. Modul - Hodnoty hodnocení

    Systém zajistí, že hodnoty parametrů poměr cena výkon a hodnocení v seznamu zkušeností a parametrů sortiment, ceny a přívětivost v seznamu hodnocení obchodů jsou celá čísla z rozsahu 1 až 10.

    Zdrojový text modulu

    Script

    Test

    Script s testem

    -- zkusím přidat záznam o zkušenosti s nepovolenou hodnotou poměru cena výkon rovno 0 -- zkusím přidat záznam o zkušenosti s nepovolenou hodnotou hodnocení rovno 0 -- zkusím přidat záznam o zkušenosti s nepovolenou hodnotou poměru cena výkon rovno 11 -- zkusím přidat záznam o zkušenosti s nepovolenou hodnotou hodnocení rovno 11 -- zkusím přidat záznam o zkušenosti s hodnotou poměru cena výkon rovno 10 -- zkusím přidat záznam o zkušenosti s hodnotou hodnocení rovno 10 -- zkusím přidat záznam o hodnocení obchodu s nepovolenou hodnotou sortiment rovno 0 -- zkusím přidat záznam o hodnocení obchodu s nepovolenou hodnotou ceny rovno 0 -- zkusím přidat záznam o hodnocení obchodu s nepovolenou hodnotou přívětivost rovno 0 -- zkusím přidat záznam o hodnocení obchodu s nepovolenou hodnotou sortiment rovno 11 -- zkusím přidat záznam o hodnocení obchodu s nepovolenou hodnotou ceny rovno 11 -- zkusím přidat záznam o hodnocení obchodu s nepovolenou hodnotou přívětivost rovno 11 -- zkusím přidat záznam o hodnocení obchodu s hodnotou sortiment rovno 10 -- zkusím přidat záznam o hodnocení obchodu s hodnotou ceny rovno 10 -- zkusím přidat záznam o hodnocení obchodu s hodnotou přívětivost rovno 10

    Záznam o proběhlém testu (log):

    Odezva na provedení testu

    Diskuse výsledku testu

    -- zkusím přidat záznam o zkušenosti s nepovolenou hodnotou poměru cena výkon rovno 0 konstatuji, ze krok testu prokázal předem očekavané chování (zahlášení chyby) -- zkusím přidat záznam o zkušenosti s nepovolenou hodnotou hodnocení rovno 0 konstatuji, ze krok testu prokázal předem očekavané chování (zahlášení chyby) -- zkusím přidat záznam o zkušenosti s nepovolenou hodnotou poměru cena výkon rovno 11 konstatuji, ze krok testu prokázal předem očekavané chování (zahlášení chyby) -- zkusím přidat záznam o zkušenosti s nepovolenou hodnotou hodnocení rovno 11 konstatuji, ze krok testu prokázal předem očekavané chování (zahlášení chyby) -- zkusím přidat záznam o zkušenosti s hodnotou poměru cena výkon rovno 10 konstatuji, ze krok testu prokázal předem očekavané chování (korektní vložení) -- zkusím přidat záznam o zkušenosti s hodnotou hodnocení rovno 10 konstatuji, ze krok testu prokázal předem očekavané chování (korektní vložení) -- zkusím přidat záznam o hodnocení obchodu s nepovolenou hodnotou sortiment rovno 0 konstatuji, ze krok testu prokázal předem očekavané chování (zahlášení chyby) -- zkusím přidat záznam o hodnocení obchodu s nepovolenou hodnotou ceny rovno 0 konstatuji, ze krok testu prokázal předem očekavané chování (zahlášení chyby) -- zkusím přidat záznam o hodnocení obchodu s nepovolenou hodnotou přívětivost rovno 0 konstatuji, ze krok testu prokázal předem očekavané chování (zahlášení chyby) -- zkusím přidat záznam o hodnocení obchodu s nepovolenou hodnotou sortiment rovno 11 konstatuji, ze krok testu prokázal předem očekavané chování (zahlášení chyby) -- zkusím přidat záznam o hodnocení obchodu s nepovolenou hodnotou ceny rovno 11 konstatuji, ze krok testu prokázal předem očekavané chování (zahlášení chyby) -- zkusím přidat záznam o hodnocení obchodu s nepovolenou hodnotou přívětivost rovno 11 konstatuji, ze krok testu prokázal předem očekavané chování (zahlášení chyby) -- zkusím přidat záznam o hodnocení obchodu s hodnotou sortiment rovno 10 konstatuji, ze krok testu prokázal předem očekavané chování (korektní vložení) -- zkusím přidat záznam o hodnocení obchodu s hodnotou ceny rovno 10 konstatuji, ze krok testu prokázal předem očekavané chování (korektní vložení) -- zkusím přidat záznam o hodnocení obchodu s hodnotou přívětivost rovno 10 konstatuji, ze krok testu prokázal předem očekavané chování (korektní vložení)

    Závěr z testování

    Triggery fungují tak, jak mají. Dovolí vložení pouze hodnot z definovaného rozmezí.

Celkový script

Odkaz na celkový script

Odezva

Závěr

V práci jsem si prakticky ozkoušel použití objektové rozšíření SQL. Tento přístup má výhody v tom, že je možné použít způsob myšlení, který se používá při vývoji v běžných programovacích jazycích jako je C++ a Java. Programátor tedy nemusí "přepínat" mezi objektovým a relačním myšlením. V některých případech je takový zápis jednodušší a čitelnější - například v případech složených cizích klíčů. Na druhou stranu je z výsledků provedených měření patrné, že objektový přístup je méně efektivní.

Další přínosnou částí práce bylo programování v PL/SQL. Procedurální rozšíření umožňují dát databázím mnohem větší možnosti práce s daty. Bohužel programování v Oracle SQL Developeru není moc komfortní. Hlášky při kompilačních chybách bývají indikovány na špatných místech a nejsou moc srozumitelné. Problém spatřuji v tom, že PL/SQL je bohužel nestandardní jazyk vyvinutý společností Oracle.

Na práci se mi nelíbila její časová náročnost. Deset dotazů a 6 modulů je příliš mnoho. Člověk poté stráví mnoho hodin jen mechanickým kopírováním reakcí na dotazy, aniž by mu to přinášelo jakýkoli intelektuální užitek. Podle mých záznamů mi vytvoření této semestrální práce zabralo přibližně 23 hodin.

Odkazy

[1] Stránky předmětu SQL - http://service.felk.cvut.cz/courses/X36SQL

[2] Rozšíření PL/SQL v Oracle 10g http://www.oracle-base.com/articles/10g/PlsqlEnhancements10g.php

[3] Formát emailové adresy http://www.regular-expressions.info/email.html