SELECT * FROM emp; SELECT ename FROM emp; (projekció) SELECT ename FROM emp WHERE ename='jones'; (szelekció) ------------------------------------------ SELECT DISTINCT deptno FROM emp; (distinct) -------------------------------- HASH UNIQUE (ha még egy order by deptno-t is beleteszünk) SORT UNIQUE SELECT ename FROM emp ORDER BY deptno; (order by) -------------------------------------- SORT ORDER BY SELECT deptno, AVG(sal) FROM emp GROUP BY deptno; (group by) ------------------------------------------------- HASH GROUP BY SORT GROUP BY SELECT deptno, AVG(sal) FROM emp GROUP BY deptno (having) HAVING SUM(sal) > 3000; ------------------------------------------------- HASH GROUP BY SORT GROUP BY SELECT ename, dname FROM emp, dept WHERE emp.deptno=dept.deptno; ---------------------------------- HASH JOIN (join) Page 1
MERGE JOIN -- Harmadik terv SELECT deptno FROM emp UNION SELECT deptno FROM dept; (union) ------------------------------------------------------- SORT UNIQUE UNION-ALL SELECT deptno FROM emp UNION ALL SELECT deptno FROM dept; (union all) ----------------------------------------------------------- UNION-ALL SELECT deptno FROM emp MINUS SELECT deptno FROM dept; (minus) ------------------------------------------------------- MINUS SORT UNIQUE SORT UNIQUE SELECT ename FROM emp WHERE deptno IN (SELECT deptno FROM dept WHERE loc='dallas'); (IN) ------------------------------------------------ MERGE JOIN VIEW VW_NSO_1 SORT UNIQUE Page 2
HASH JOIN SEMI!!! Figyeljünk a lehetséges NULL értékekre az alábbi két lekérdezésben. NULL elvileg elofordulhat az alkérdésben is, és a külso SELECT deptno oszlopában is. Ezen kívül az is elofordulhat, hogy a belso SELECT nem ad vissza egyetlen sort sem. X NOT IN (NULL, Y) -> UNKNOWN NULL NOT IN (NULL, Y) -> UNKNOWN NULL NOT IN (üres halmaz) -> TRUE SELECT ename FROM emp WHERE deptno NOT IN (SELECT deptno FROM dept WHERE loc='dallas'); (NOT IN) ------------------------------------------------!!! Az elozo lekérdezésben a lehetséges NULL értékek miatt nem tud hash (anti)joint végezni. Az alábbi két utasítás lefuttatása után már tudna, lásd a következo lekérdezést. alter table dept modify(deptno not null); alter table emp modify(deptno not null); SELECT ename FROM emp WHERE NOT EXISTS (SELECT * FROM dept WHERE loc='dallas' (NOT EXISTS) AND emp.deptno=dept.deptno); ----------------------------------------- HASH JOIN ANTI Végrehajtási tervek indexek használatával create index ename on emp(ename); create unique index empno on emp(empno); SELECT * FROM emp WHERE ename = 'KING'; (index) --------------------------------------- TABLE ACCESS BY INDEX ROWID EMP INDEX RANGE SCAN ENAME SELECT ename FROM emp WHERE ename = 'KING'; (csak_index) ------------------------------------------- INDEX RANGE SCAN ENAME Page 3
A fenti tervbol látható, hogy ha nem muszáj akkor nem is használja a táblát, csak az indexet. SELECT * FROM emp WHERE empno = 7900; (unique_index) ------------------------------------- TABLE ACCESS BY INDEX ROWID EMP INDEX UNIQUE SCAN EMPNO A fenti tervbol látható, hogy ha lehetséges, célszeru megadni a UNIQUE kulcsszót az index létrehozásakor. SELECT * FROM emp WHERE ename='king' OR ename='jones'; ----------------------------------------------------- INLIST ITERATOR TABLE ACCESS BY INDEX ROWID EMP INDEX RANGE SCAN ENAME SELECT * FROM emp WHERE ename='king' OR ename IS NULL; ----------------------------------------------------- Bonyolultabb lekérdezések végrehajtási terve Adjuk meg azoknak az osztalyoknak az azonositojat, nevet es az osztalyon dolgozok atlagfizeteset, amely osztalyoknak nincs olyan dolgozoja, aki a 3-as fizetesi kategoriaba esik. (Deptno, Dname, Atlag_fizetes) semaban SELECT dept.deptno, dname, avg(sal) FROM emp, dept WHERE emp.deptno=dept.deptno AND NOT EXISTS (SELECT * FROM emp emp2, salgrade WHERE emp2.deptno=dept.deptno AND sal BETWEEN losal AND hisal AND grade=3) GROUP BY dept.deptno, dname; Ha semmilyen index nincs a táblákra, akkor a terv az alábbi ---------------------------------------- SORT GROUP BY MERGE JOIN Page 4
TABLE ACCESS FULL SALGRADE HASH GROUP BY HASH JOIN HASH JOIN ANTI VIEW VW_SQ_1 TABLE ACCESS FULL SALGRADE Ha van index az EMP és DEPT táblák deptno oszlopára és a SALGRADE tábla grade oszlopára, akkor a terv az alábbi ------------------------------------------------- SORT GROUP BY TABLE ACCESS BY INDEX ROWID EMP INDEX RANGE SCAN EMP_DEPTNO_I TABLE ACCESS BY INDEX ROWID SALGRADE INDEX RANGE SCAN SALGRADE_I TABLE ACCESS BY INDEX ROWID EMP INDEX RANGE SCAN EMP_DEPTNO_I Kérdés: hogyan tudja a legutolsó sorban az indexet használni? Mit keres az indexben? -> Ebben segít a PLAN_TABLE.ACCESS_PREDICATES (_PREDICATES, PROJECTION) A muvelet az elso sorhalmazt szuri meg a második sorhalmaz alapján. Az utóbbi tervnél látható, hogy a második sorhalmazt folyamatosan állítja elo az elso sorhalmazbeli sor alapján Más táblákra vonatkozó lekérdezések Cikk (ckod, cnev, szin, suly) Projekt (pkod, pnev, helyszin) Szallito (szkod, sznev, statusz, telephely) Szallit (szkod, ckod, pkod, mennyiseg, datum) x A tervekben néhol a PLAN_TABLE.position oszlop értéke is szerepel, Page 5
hogy / \ lássuk az azonos szinten levo muveleteket milyen sorrendben végzi. / \ 1 2 -- Nem használ indexet, nem alakítja át a kifejezést select sum(suly) from cikk where ckod+1=2; ------------------------------------------ TABLE ACCESS FULL CIKK -- Itt egyszerusít, és használ indexet select sum(suly) from cikk where ckod=floor(sqrt(44*23)); --------------------------------------------------------- TABLE ACCESS BY INDEX ROWID CIKK INDEX UNIQUE SCAN C_CKOD -- Meddig látja célszerunek az index használatát a költség alapú -- optimalizáló? Ennél pl. nem használ indexet select sum(suly) from cikk where ckod < 300; -------------------------------------------- TABLE ACCESS FULL CIKK -- Ennél még használ indexet select sum(suly) from cikk where ckod < 10; ------------------------------------------- TABLE ACCESS BY INDEX ROWID CIKK INDEX RANGE SCAN C_CKOD -- Adjuk meg azokat a szállitó, projekt párokat, ahol a szallitó -- telephelye megegyezik a projekt helyszínével és a szállító által -- ehhez a projekthez szállított cikkek összmennyisége > 5000 SELECT szallito.szkod, projekt.pkod, telephely FROM szallito, szallit, projekt WHERE szallit.szkod=szallito.szkod AND szallit.pkod=projekt.pkod AND telephely=helyszin GROUP BY szallito.szkod, projekt.pkod, telephely HAVING SUM(mennyiseg) > 5000; --------------------------------------------------------------- SORT GROUP BY TABLE ACCESS FULL PROJEKT Page 6
TABLE ACCESS BY INDEX ROWID SZALLIT INDEX RANGE SCAN SZT_PKOD TABLE ACCESS BY INDEX ROWID SZALLITO INDEX UNIQUE SCAN SZO_SZKOD -- Mint az elozo feladat, csak most a piros cikkekre vonatkozó -- mennyiségeket adjuk össze SELECT szallito.szkod, projekt.pkod, telephely FROM szallito, szallit, projekt, cikk WHERE szallit.szkod=szallito.szkod AND szallit.pkod=projekt.pkod AND szallit.ckod=cikk.ckod AND szin='piros' AND telephely=helyszin GROUP BY szallito.szkod, projekt.pkod, telephely HAVING SUM(mennyiseg) > 500; ---------------------------------------------------------------- 1 SORT GROUP BY 1 1 1 1 TABLE ACCESS BY INDEX ROWID CIKK 1 INDEX RANGE SCAN C_SZIN 1 TABLE ACCESS BY INDEX ROWID SZALLIT 2 INDEX RANGE SCAN SZT_CKOD 1 TABLE ACCESS BY INDEX ROWID PROJEKT 2 INDEX UNIQUE SCAN P_PKOD 1 TABLE ACCESS BY INDEX ROWID SZALLITO 2 INDEX UNIQUE SCAN SZO_SZKOD 1 HASH GROUP BY HASH JOIN TABLE ACCESS FULL CIKK TABLE ACCESS FULL SZALLIT TABLE ACCESS BY INDEX ROWID SZALLITO INDEX UNIQUE SCAN SZO_SZKOD TABLE ACCESS BY INDEX ROWID PROJEKT -- Adjuk meg a piros cikkekre vonatkozó összes szállítások összmennyiségét... A lekérdezést most nem adom meg, mert ez a beadandó feladat. ---------------------------------------------------------------- 1 1 TABLE ACCESS BY INDEX ROWID CIKK 1 INDEX RANGE SCAN C_SZIN 1 Page 7
TABLE ACCESS BY INDEX ROWID SZALLIT 2 INDEX RANGE SCAN SZT_CKOD 1 Adjunk olyan hintet, hogy ne használjon indexet, ill. csak 1 indexet használjon.... -- Adjunk olyan hintet, hogy SORT-MERGE JOIN-t végezzen... ---------------------------------------------- 9 1 MERGE JOIN 1 1 TABLE ACCESS BY INDEX ROWID CIKK 1 INDEX RANGE SCAN C_SZIN 1 2 TABLE ACCESS FULL SZALLIT 1 Ha a nem piros cikkekre vonatkozó összmennyiséget kérdezzük le, az sokkal tovább fog futni, mert a köztes eredmény mérete nagyobb, és ezt rendeznie kell. -- Most egy clusterre került a cikk és szállít tábla create cluster ckod_cl(ckod integer); create index ckod_i on cluster ckod_cl; create table cikk_ind_cl(...) cluster ckod_cl(ckod); create table szallit_ind_cl(...) cluster ckod_cl(ckod); -- Adjuk meg a szállított piros cikkek összmennyiségét... ----------------------------------------------------------- 1 1 TABLE ACCESS BY INDEX ROWID CIKK_IND_CL 1 INDEX RANGE SCAN C_SZIN1 1 TABLE ACCESS CLUSTER SZALLIT_IND_CL 2 TABLE ACCESS FULL CIKK_IND_CL TABLE ACCESS CLUSTER SZALLIT_IND_CL INDEX UNIQUE SCAN CKOD_I -- Most egy hash clusterre került a cikk és szállít tábla create cluster ckod_hash(ckod integer); create table cikk_hash_cl(...) cluster ckod_hash(ckod); create table szallit_hash_cl(...) cluster ckod_hash(ckod); -- Adjuk meg a szállított piros cikkek összmennyiségét... Page 8
------------------------------------------------------------- 1 1 TABLE ACCESS BY INDEX ROWID CIKK_HASH_CL 1 INDEX RANGE SCAN SZIN_2 1 TABLE ACCESS HASH SZALLIT_HASH_CL 2 TABLE ACCESS FULL CIKK_HASH_CL TABLE ACCESS HASH SZALLIT_HASH_CL -- Join nélkül is hash módszerrel olvassa a szallit táblát select * from szallit_hash_cl where ckod=1; ------------------------------------------- TABLE ACCESS HASH SZALLIT_HASH_CL Példa arra, amikor két indexet használ egy táblához. A sorazonosítók metszetét képezi, majd ezen mutatók mentén olvassa a táblát. select sum(mennyiseg) from szallit where ckod=9 and szkod=9; ------------------------------------------------------------ TABLE ACCESS BY INDEX ROWID SZALLIT AND-EQUAL INDEX RANGE SCAN SZT_CKOD INDEX RANGE SCAN SZT_SZKOD A két index által visszaadott sorazonosítókat más módszerrel is össze tudja fésülni. Az alábbi tervhez nem kell bitmap indexnek lennie. A szükséges bitvektorokat az indexbol beolvasott sorazonosítók alapján is fel tudja építeni, majd ezekkel végez muveletet, végül visszaalakítja aorazonosítókká. select sum(mennyiseg) from szallit where ckod=9 and szkod=9; ------------------------------------------------------------ TABLE ACCESS BY INDEX ROWID SZALLIT BITMAP CONVERSION TO ROWIDS BITMAP AND BITMAP CONVERSION FROM ROWIDS INDEX RANGE SCAN SZT_CKOD BITMAP CONVERSION FROM ROWIDS INDEX RANGE SCAN SZT_SZKOD Példa arra, hogy azonos tervek még különbözo futási idot adhatnak. select sum(mennyiseg) from cikk,szallit where cikk.ckod < 999; Page 9
-------------------------------------------------------------- 1 1 TABLE ACCESS FULL SZALLIT 1 TABLE ACCESS FULL CIKK 2 Ha ckod > 999-et adunk meg akkor sokkal gyorsabb lesz, pedig a terv ugyanaz. -- A fenti rendezés () még mindig sokkal olcsóbb, mint az alábbi, ami -- nagyon sokáig fut (SORT ORDER BY). select * from cikk,szallit order by cikk.ckod ------------------------------------------------ SORT ORDER BY TABLE ACCESS FULL SZALLIT TABLE ACCESS FULL CIKK Page 10