2012. augusztus 27., hétfő

"Forró" adattárház táblák azonosítása


Egy adattárház vizsgálata közben feltettem magamnak a kérdést, hogy vajon melyek a felhasználók által leggyakrabban használt táblák. Erre a kérdésre, viszonylag könnyen választ lehet kapni az alábbi lekérdezéssel:

select
  t.object_name, s.statistic_name, sum(s.value) value
from
  dba_objects t,
  v$segstat s
where t.object_id = s.OBJ#
  and s.value <> 0
  and s.statistic_name = 'logical reads'
group by t.object_name, s.statistic_name
order by sum(s.value) desc
;

Adattárháznál szinte mindig az IO a szűk keresztmetszet, ezért célszerű megnézni, hogy mely táblák generálják a fizikai olvasásokat:

select
  t.object_name, s.statistic_name, sum(s.value) value
from
  dba_objects t,
  v$segstat s
where t.object_id = s.OBJ#
  and s.value <> 0
  and s.statistic_name = 'physical reads'
group by t.object_name, s.statistic_name
order by sum(s.value) desc
;

A fizikai olvasásokat vizsgálva kíváncsi lettem, hogy vajon milyen objektumok vannak bent az Oracle cahce - ben? Ezt az alábbi lekérdezéssel néztem meg.

select
  o.owner,
  o.object_name,
  b.block_size object_block_size,
  count(*) num_of_blocks_in_cache,
  min(s.segment_blocks) total_num_of_blocks,
  round(count(*) / min(s.segment_blocks) * 100) as percentage_in_cache,
  round(block_size * count(*) /1024/1024) as object_cace_size_mb,
  round(sum(block_size * count(*)) over ( partition by block_size) /1024/1024) as full_cace_size_mb
from
  v$bh b,
  dba_objects o,
  v$tablespace t,
  dba_tablespaces b,
  (
    select
      t.owner, t.segment_name, sum(blocks) segment_blocks
    from dba_segments t
    group by t.owner, t.segment_name
  ) s
where b.objd = o.object_id
  and b.TS# = t.TS#
  and t.name = b.tablespace_name
  and s.owner = o.owner
  and s.segment_name = o.object_name
group by o.owner, o.object_name, b.block_size
order by count(*) desc
;

A fenti információkat feldolgozva, a cache megfelelő méretezésével; cache hintek, cache opciók beállításával lehet csökkenteni a rendszer IO terhelését, azaz növelni a rendszer összteljesítményét.

2012. július 6., péntek

Fejlesztői rutinműveletek automatizálása AutoHotkey - vel.



Egy újabb hasznos programmal bővült a fejlesztői eszköztáram. A legújabb Pl/Sql Developer makró funkcióit próbálgattam, s rá kellett jönnöm, hogy a billentyűkombinációk visszajátszása nem minden esetben történik meg korrektül, azaz nem tudom vele rendesen automatizálni a rutin műveleteket, ezért elővettem az AutoHotkey (AHK) programot, melyet már régebbről ismertem.

Az AutoHotkey egy ingyenes script program, melynek segítségével inputokat küldhetünk a Windows programjainknak, azaz alkalmas a Pl/Sql Developer makró funkciójának kiváltására.

Egyik vesszőparipám, hogy gyakran van szükségem arra, hogy egy tény táblában levő kód értékhez lekérdezzem egy kódtáblából a kód leírását. A kódtábla lekérdezésre persze van egy bejáratott, paraméterezett scriptem. AutoHotkey segítségével ennek a feladatnak az automatizálása így oldható meg:

#q::
 send ^c
 send !f
 send o
 send s
 WinWaitActive Open
 sendinput C:\path\select dim table.sql{ENTER}
 send {F8}
 send ^v
 send {ENTER}
return

A ResultGrid - ben dupla kattintással kijelölöm a kérdéses cella tartalmát, majd a Windows+q billentyűkombinációt lenyomva az AHK futtatja a scriptemet a cella értékkel paraméterezve. A Pl/Sql Developer nem nyit újabb ablakot, ha már egyszer meg lett nyitva az sql fájl, hanem csak a már meglevő ablakot aktiválja, azaz a script kényelmesen futtatható többször is, nem kell az ablakokat csukogatni.

A script bővíthető úgy is, hogy az AHK automatikusan átváltson a megfelelő Pl/Sql Developer ablakra. Ez akkor jön jól, amikor a dokumentációt olvasom és az abban szereplő információ alapján akarok lekérdezést futtatni.

#q::
 send ^c
 WinActivate PL/SQL Developer - user@database
 send !f
 send o
 send s
 WinWaitActive Open
 sendinput C:\path\select dim table.sql{ENTER}
 send {F8}
 send ^v
 send {ENTER}
return

Bonyolultabb rutinművelet automatizálásával is próbálkozom, erre példa az alábbi kód, melyet arra használok, hogy egy már meglevő select - ből subselect - et készítsek. A script a kijelölt szöveget tabulálja és a select * from (#kijelölt szöveg#) kódot eredményezi.

#p::
 sendinput {TAB}
 sendinput ^x
 sendinput {HOME}
 sendinput select{ENTER}
 sendinput {TAB}*{ENTER}
 sendinput {HOME}from ({ENTER}
 sendinput {TAB}^v{ENTER}
 sendinput {HOME})
return

Amikor kódrészletet másolok át alkalmazások között, akkor gyakran szükségem van rá, hogy csak a szövegtartalmat vigyem át, a formázást figyelmen kívül hagyva. AHK - val ez az alábbi scripttel oldható meg. Én ezt a Windows+c gombra raktam, amit a Ctrl+c alternatívájaként tudok alkalmazni.

#c::
 send ^c
 clipboard = %clipboard%
return

Nemrég kezdtem el használni az AHK - t, még rengeteg potenciált látok benne, bízom benne, hogy megszabadít az unalmas, időpazarló rutinmunkától.


2012. június 7., csütörtök

Hatékony eljárás aktív dimenzió rekordok történetének lekérdezésére.



A minap belefutottam egy feladatba, melyben arra volt szükség, hogy egy dimenzió táblából leválogassam azon elemek történetiségét, melyeknek van éppen érvényes rekordja. Első nekifutásra az alábbi megoldással álltam elő:

create table dim_table
(
  code_1 number,
  desc_1 varchar2(200),
  start_of_validity date,
  end_of_validity date
);

select
  hist.code_1,
  hist.desc_1,
  hist.start_of_validity,
  hist.end_of_validity
from
  dim_table curr,
  dim_table hist
where curr.start_of_validity <= sysdate
  and curr.end_of_validity > sysdate
  and curr.code_1 = hist.code_1;

Mivel hatalmas tábláról volt szó és több hónapra visszamenőlegesen kellett futtatni a feldolgozást, ezért elkezdtem gondolkodni rajta, hogyan lehet lefaragni a futási időből. Az alábbi megoldással rukkoltam elő:

select
  code_1,
  desc_1,
  start_of_validity,
  end_of_validity
from (
  select
    curr.code_1,
    curr.desc_1,
    curr.start_of_validity,
    curr.end_of_validity,
    max(case
      when curr.start_of_validity <= sysdate and curr.end_of_validity > sysdate then 1
      else 0
    end) over (partition by code_1) as curr_ind
  from
    dim_table curr
)
where curr_ind = 1;

Ez utóbbi megoldás ugyanazt az eredményhalmazt adja, azonban a végrehajtás során csak egyszer kell felolvasni az alaptáblát. Az én esetemben ez közel megfelezte a végrehajtási időt.

2012. május 2., szerda

SQL Tuning, futó lekérdezések memória és temp használatának megjelenítése végrehajtási lépésenként.


Ambrus Gábor kollégámtól kaptam az alábbi, praktikus script - et, melynek segítségével megtekinthető egy éppen futó sql végrehajtási terve, s a végrehajtási tervhez kapcsolódó egyes lépések aktuális memória és temp használata. Ez a lekérdezés nagyon megtetszett nekem, mert segítségével betekintést nyerhetünk lekérdezésünk végrehajtási állapotába, a memória és temp értékek vizsgálatával könnyen kiszúrhatjuk, ha valahol "hiba" csúszott a végrehajtási tervbe.

A lekérdezés második sorába kell beilleszteni a futtatás előtt a vizsgálandó futó lekérdezés sql_id azonosítóját.


with sqlid as (
    select '9c9qwv489rxfk' sql_id from dual
)
select
    woac.temp_mb,
    woac.mem_mb,
    substr(translate(
        substr(sys_connect_by_path(branch, ','), 1, length(sys_connect_by_path(branch, ',')) - 2) ||
            case when branch = '. ' then '`-' else '|-' end,
        ',.',
        '  '
    ), 4) || operation operation,
    plta.options,
    plta.object_owner,
    plta.object_name,
    plta.object_alias,
    plta.cardinality,
    plta.other_tag,
    plta.access_predicates,
    plta.filter_predicates,
    plta.partition_start,
    plta.partition_stop,
    plta.partition_id
from
    (
        select
            sql_hash_value,
            sql_id,
            operation_id,
            sum(tempseg_size/1048576) temp_mb,
            sum(actual_mem_used/1024/1024) mem_mb
        from
            v$sql_workarea_active
        group by
            sql_hash_value,
            sql_id,
            operation_id
    ) woac,
    (
        select
            pl.*,
            nvl2(lead(pl.id) over (partition by pl.parent_id order by pl.position), '| ', '. ') branch
        from
            v$sql_plan pl,
            sqlid
        where
            pl.sql_id = sqlid.sql_id and
            pl.child_number = 0
    ) plta
where
    woac.sql_hash_value (+) = plta.hash_value and
    woac.sql_id (+) = plta.sql_id and
    woac.operation_id (+) = plta.id
connect by
    prior plta.id = plta.parent_id
start with
    plta.parent_id is null
order siblings by plta.position;


2012. január 11., szerda

Ingyenesen elérhető tesztsorok Oracle vizsgákhoz.

Célul tűztem ki magamnak, hogy további Oracle minősítéseket szerzek meg, leteszem az Oracle Database 11g: Administration I (1Z0-052) vizsgát.

Elkezdtem kutakodni az interneten tananyagok, vizsgasorok után s rátaláltam a http://www.examcollection.com/ oldalra. Erről az oldalról ingyenesen letölthetőek vizsgasorok. Az 1Z0-052 vizsgához is van legalább egy tucatnyi vizsgasoruk. Az oldal felhasználóinak visszajelzései alapján a vizsgasorok aktuálisak és jól használhatóak.

Az egyetlen trükk, hogy a Visual CertExam Suite programot meg kell vásárolni a letölthető vce fájlok megtekintéséhez, azonban kisebb kutakodás után sikerült rátalálnom a lenti linken letölthető kis programra, mely képes a vizsgasorok megjelenítésére, azaz használatával sikeresen fel lehet készülni.


Az ExamCollection számos vizsgához nyújt felkészülési anyagokat, ezért egy klikket mindenképpen megér a site.

Sok sikert a vizsgákhoz!

2012. január 2., hétfő

Tippek az Oracle Database 11g: Data Warehousing Certified Implementation Specialist minősítés megszerzéséhez.

A nyáron rátaláltam az Oracle oldalain a fenti, adattárház szakmai minősítésre. Úgy gondoltam, hogy ha már évek óta Oracle alapú adattárházak építésével foglalkozom, akkor illik megszereznem ezt a minősítést.

Átnéztem az Oracle által kiírt vizsgatematikát és az Oracle partnerek számára biztosított oktatási anyagot s világossá vált, hogy ennek a vizsgának is csak úgy érdemes nekimenni, ha előtte egy teszt programmal alaposan felkészülünk.

Az SQL és PL/SQL vizsgák megszerzésénél a uCertify platform bizonyult hasznosnak, ezért most is a uCertify felkészítő anyagát vettük meg. A vizsgán ért minket a meglepetés, hogy a uCertify anyag csak egy harmadában fedi le a tényleges vizsgakérdéseket. Ennek ellenére sikerült első nekifutásra átmenni a vizsgán, azonban ha valaki fel akar készülni, akkor inkább a PassGuide – ot ajánlom, az ő anyaguk jobban illeszkedik a tényleges vizsgakérdésekhez.

A vizsgára való felkészüléskor az alábbi témaköröket célszerű alaposan átnézni:
  • Adaptive parallelism
  • Oracle Exadata
    • teljesítménynövelő módszerek
    • adattárolási képességek
  • Tömörítési funkciók
  • SQL Result Cache működése
    • result set – ek típusai
    • engedélyezés
    • cache tartalom milyen eseményekre változik
  • Materializált nézetek, frissítési típusok
  • Direct path load – ot eredményező adatbázis műveletek
  • Partícionálási típusok 
    • partícionálás előnyei (pruning)
    • partition-wise joins
  • Resource Manager működése
  • ODI felépítés, template – ek, Knowledge Modul – ok funkciója
Kollégáim találtak rá az alábbi két blog bejegyzésre, melyek gyakorlatilag teljesen lefedik a vizsga anyagát, ez a két cikk elengedethetetlen a felkészüléshez:

Oracle 1z0-515 Data Warehousing 11g Essentials 1/2
Oracle 1z0-515 Data Warehousing 11g Essentials 2/2

2011. július 19., kedd

Az adattárház konzisztenciáját automatikusan ellenőrizni kell!

Az egyik projekt munkám során az adattárház adatainak egy részhalmazát egy különálló szerverre replikáztuk. A replika frissítése deltatöltéseket is tartalmazott. A megvalósítás során felmerült a kérdés, hogy, na de honnan fogjuk észrevenni, ha a replikációs eljárásunk hibázik, azaz az eredeti adathalmazunk és a másolat már nem konzisztens, eltér egymástól.

Ennek a kérdésnek már tervezéskor is fel kellett volna merülnie, nem csak a megvalósítás közben. Azért is írom ezt a blog bejegyzést, hogy legközelebb nekem is hamarabb eszembe jusson, hogy az automatikus konzisztencia ellenőrzéseket is bele kell tervezni a megvalósításba, nem szabad elfeledkezni róluk.

Murphy törvénye szerint, ami elromolhat az előbb utóbb el is romlik. Megelőzendő, hogy a végfelhasználók vegyék először észre a hibát, a töltési folyamat megvalósításába ellenőrzéseket kell beiktatni. Nem kell az ellenőrzés alatt nagyon komoly dologra gondolni, az aktuális szituációban az is elegendőnek bizonyult, hogy egy segédtáblában nyilvántartjuk a forrásrendszerben levő táblák rekordszámát és ezt a rekordszámot ellenőrizzük a delta csomagok bedolgozása után. Egy ilyen egyszerű ellenőrzés már biztosítani tudja azt, hogy automatikusan értesüljünk arról, hogy hiba csúszott a gépezetbe, biztosítani tudja, hogy ne csak késve értesüljünk a hibáról, amikor annak javítása már sokkal időigényesebb lehet.

Egy adattárház feldolgozásai nagyon komplexek is lehetnek, több ponton is van lehetőség hibára, ezért ahol delta csomagok feldolgozása történik, ott célszerű megvalósítani egy egyszerű ellenőrzési eljárást is, hogy biztosak lehessünk adataink konzisztenciájában.