Oracle random fact:V DBMS_SQL.PARSE lze specifikovat edici pod kterou kód poběží;

PL/SQL programátor bloguje – vývoj aplikací pod databází Oracle

Tipy a triky s PL/SQL


Seminář na téma Cloud Computing od Oracle v Praze

Jeden horký tip na seminář přímo od Oracle v Praze na Chodově. Dne 3.7.2013 bude Oracle pořádat seminář na téma Cloud Computing, který je zdarma. Počet míst je omezen, takže je nutné se registrovat, zde:

http://www.oracle.com/us/dm/196708-emeafm13047780mpp019-oem-1957275.html

A chovat se slušně a odregistrovat se v případě, že nebude moci. Ať jsou tam místa pro ostatní. Je to velice podobné snídaním, které kdys (nebo snad ještě?) Oracle pořádal jako zdarma přednášky/semináře, typicky na téma databáze nebo nové produkty.

středa, 3. červenec 2013, 08:30 – 11:10,V Parku 2294/4, Praha 4
Info ze stránek Oracle:

  • Podíváme se, jak vám může Cloud computing pomoci realizovat požadované cíle
    v obchodní i IT strategii.
  • Jakým způsobem začít budovat strategii v oblasti Cloud computing služeb.
  • Způsob implementace Cloud computingu s využitím architektonických a
    technologických vzorů.
  • Co všechno vám v této oblasti může nabídnout společnost Oracle.
  • Jak vám Oracle může pomoci s každým aspektem plánování, nasazení, monitorování a správy Cloud prostředí.

Uvidíme se tam a nezapomeňte se oholit a pořádně obléci – Oracle měl v recepci vždycky luxusní samičky ;)

Written by AZOR

June 12th, 2013 at 7:50 pm

Posted in Oracle

Oracle do *.BMP (a možná dále do *.JPEG a *.MOV) (část 1)

Musím říct, že jsem několikrát ve svém životě potřeboval z DB vygenerovat nějaký report a pokaždé když došlo na potřebu grafické reprezentace, snažil jsem se tomu zuby nehty vyhnout. Jenže obrázky jsou sexy, ne?  Takže můj cíl je nyní generovat obrázky z databáze. Zatím pouze obrázky a pouze *.BMP. Mě by se totiž mnohem více hodila komprimovaná videa, nicméně je třebas dekomponovat. Ostatně generování  *.BMP bude mít jednu krásnou vlastnost – bude možné vidět případný sub-výsledek až bych třebas psal JPEG komprimaci v PL/SQL. Mnohem rychlejší by bylo napsat to v Javě a javu si provolat či jí přímo loadnout do Oracle – funkční, rychlé, efektivní – ale nudné.

Vím o jednom problému, který mi čeká a o kterém ještě nemám úplnou představu jak ho řešit – je třeba do obrázku mimo kreslení psát, což znamená mít představu jako takové písmeno (“A”) bude v bitmapě vypadat a zatímco v Javě to stačí drawStringnout na Canvas (či Canvas2d) tady to bude vyžadovat mnohem více. Což třebas povede na nějaké čtení fontů(?) a loadování do DB a o to to bude zajímavějšejší, inu, uvidíme.

Takže hurá do hébičkování !

Bitmapa (jako BMP) vypadá jako soubor pixelů a nic víc. Nicméně i tak má BMP soubor nějakou hlavičku, kterou je třebas zapsat: Při čtení článku na wiki jsem dokonce zjistil, že BMP umožňuje Huffamanovo kódování a tedy bezztrátovou komprimaci v jisté omezené podobě, což jsem do dneška netušil.

http://en.wikipedia.org/wiki/File:BMPfileFormat.png

Což znamená, že bílý jednopixelový (1×1) obrázek nejsou 3 bajty (24 bitů – 8×3 barvy), ale 58 bajtů:

Jeden bilý pixel v BMP

Pro pochopení jsem si vyzkoušel nějakou úpravu (modře) – konkrétně jsem z 01 přepsal pixely na 02 (2x 2x) a přidal 12 bajtů:

Čtyři pixely v BMP (uprava v hexaeditoru)

Fajn, to by zafungovalo, takže společně s obrázkem z wikipedie už je asi pomalu možné nějaké BMP začít tvořit.  Nejprve nastřelení nějakého minimálního kódu, že je to správný směr:

1) Založení adresáře, kam se budou cpát BMP soubory:
CREATE DIRECTORY output_bmp AS 'F:\bmp_output';

2) Úplně minimální kód na zkoušku:
declare
bmp_file utl_file.file_type;
un_used_1 RAW(4):=hextoraw('42')||hextoraw('4d');
begin
bmp_file:=utl_file.fopen('OUTPUT_BMP','test.bmp','wb');
utl_file.put_raw(bmp_file,un_used_1,true);
if utl_file.is_open(bmp_file) then
utl_file.fclose_all;
end if;
end;

Je to opravdu minimální kód, který do souboru test.bmp zapíše pouze 42 a 4D (hex), což odpovídá ascii textu ‘BM‘ a je to první část hlavičky bitmapového souboru. Což v hexaeditoru (použivám WinHex 17.0 a vřele doporučuji – umí přímý zápis na disk i do RAM), vypadá takto:

První část hlavičky BMP souboru

Fajn, to by bylo a nyní minimální kód, pro vygenerování nejjednoduššího BMP – hlavičku, jsem sprostě opráskl z wikipedie:

declare
/* uvodni BMP hlavička BMP */
static_magic_header RAW(2):=hextoraw('42')||hextoraw('4d');
/* velikost obrázku v B */
variable_image_size RAW(4):=hextoraw('46')||hextoraw('00')||hextoraw('00')||hextoraw('00');
/* aplication specific - takze se podepišu AZOR - AZ */
static_aplication_1 RAW(2):=hextoraw('41')||hextoraw('5A');
/* aplication specific - takze se podepišu AZOR - OR */
static_aplication_2 RAW(2):=hextoraw('4F')||hextoraw('52');
/* kde končí hlavička */
static_head_end RAW(4):=hextoraw('36')||hextoraw('00')||hextoraw('00')||hextoraw('00');
/* délka DIB hlavičky */
static_dib_size RAW(4):=hextoraw('28')||hextoraw('00')||hextoraw('00')||hextoraw('00');
/* sířka obrázku */
variable_image_width RAW(4):=hextoraw('02')||hextoraw('00')||hextoraw('00')||hextoraw('00');
/* výška obrázku */
variable_image_height RAW(4):=hextoraw('02')||hextoraw('00')||hextoraw('00')||hextoraw('00');
/* počet planes */
static_image_planes RAW(2):=hextoraw('01')||hextoraw('00');
/* počet barev - 24 bitová paleta */
static_image_bits RAW(2):=hextoraw('18')||hextoraw('00');
/* bi_rgb */
static_bi_rgb RAW(4):=hextoraw('00')||hextoraw('00')||hextoraw('00')||hextoraw('00');
/* velikost pixel array (dat) - a BEZ KOMPRSE*/
variable_raw_size RAW(4):=hextoraw('10')||hextoraw('00')||hextoraw('00')||hextoraw('00');
/* pixels/metters - horizontalne i vertikalne pouziju jednu promennou */
static_pix_metter RAW(4):=hextoraw('13')||hextoraw('0B')||hextoraw('00')||hextoraw('00');
/* nezbytné barvy - nulla */
static_colors RAW(4):=hextoraw('00')||hextoraw('00')||hextoraw('00')||hextoraw('00');
/* A KONEČNĚ JEDNOTLIVÉ PIXELY (prvně však separátor) */
static_pix_separator RAW(2):= hextoraw('00')||hextoraw('00');
data_pix_1_1 RAW(3):=hextoraw('00')||hextoraw('FF')||hextoraw('FF');
data_pix_1_2 RAW(3):=hextoraw('00')||hextoraw('00')||hextoraw('FF');
data_pix_2_1 RAW(3):=hextoraw('FF')||hextoraw('00')||hextoraw('FF');
data_pix_2_2 RAW(3):=hextoraw('FF')||hextoraw('00')||hextoraw('FF');
bmp_file utl_file.file_type;
begin
bmp_file:=utl_file.fopen('OUTPUT_BMP','test_2.bmp','wb');
/* postupné zapisování všech hlaviček */
utl_file.put_raw(bmp_file,static_magic_header,true);
utl_file.put_raw(bmp_file,variable_image_size,true);
utl_file.put_raw(bmp_file,static_aplication_1,true);
utl_file.put_raw(bmp_file,static_aplication_2,true);
utl_file.put_raw(bmp_file,static_head_end,true);
utl_file.put_raw(bmp_file,static_dib_size,true);
utl_file.put_raw(bmp_file,variable_image_width,true); -- šířka
utl_file.put_raw(bmp_file,variable_image_height,true); -- výška
utl_file.put_raw(bmp_file,static_image_planes,true);
utl_file.put_raw(bmp_file,static_image_bits,true);
utl_file.put_raw(bmp_file,static_bi_rgb,true);
utl_file.put_raw(bmp_file,variable_raw_size,true);
utl_file.put_raw(bmp_file,static_pix_metter,true);
utl_file.put_raw(bmp_file,static_pix_metter,true);
utl_file.put_raw(bmp_file,static_colors,true);
utl_file.put_raw(bmp_file,static_colors,true);
/* a konečně data */
utl_file.put_raw(bmp_file,data_pix_1_1,true);
utl_file.put_raw(bmp_file,data_pix_1_2,true);
/* separátor řádku */
utl_file.put_raw(bmp_file,static_pix_separator,true);
/* druhý řádek */
utl_file.put_raw(bmp_file,data_pix_2_1,true);
utl_file.put_raw(bmp_file,data_pix_2_2,true);
/* ukončení souboru */
utl_file.put_raw(bmp_file,static_pix_separator,true);
/* a zavřít soubor */
if utl_file.is_open(bmp_file) then
utl_file.fclose_all;
end if;
end;

A wohoho – 4pixelový výsledek uložený v souboru test_2.bmp vypadá po zvětšení takto :

Vygenerované BMP

Vygenerované BMP

Bohužel jsem změnil bezhlavě barvu a vypadla z toho růžová :/, zrovna taková hloupá barva. Kód rozhodně není hezký a v nějakém dalším díle ho upravím. Zatím jsem vytipoval části hlaviček, které nebudu měnit (prefix static_) a ty které se s velikostí obrázku budou muset měnit a přepočítávat (prefix variable_). Vygenerovaný obrázek vypadá pak v hexaeditoru:

První BMP v Oracle zobrazená v WinHex

První BMP v Oracle zobrazená v WinHex

Tak a to by bylo pro tento díl všechno ;) V druhém to navrhuji vykrášlit a udělat nějakou funkci, která mi z BLOBu vrátí přímo hlavičku. A taky funkci, která vygeneruje prázdný obrázek. Ještě s tím bude spousta legrace.

Written by AZOR

June 2nd, 2013 at 9:36 pm

Posted in PL/SQL,Tutoriály

Statistika segmentů – V$SEGMENT_STATISTICS

Dnes tip na jedno úžasné view o kterém zrovna dlouho nevím – V$SEGMENT_STATISTICS. Obecně v Oracle platí, že v tabulkách a pohledech lze nalézt téměř vše s menšíma výjimkami - například binding proměnnou v projection selectu jinak než trace eventem nedohledáme (na rozdíl od binding proměnných v predikátech), což nám třeba kdysi vadilo na Siebelu, kdy tagoval sql, které pral do databáze select xx ,’zde’ from yyy;  Ale zpět k pohledu V$SEGMENT_STATISTICS, jak název napovídá je tam statistika segmentů.

Dokuementace: http://docs.oracle.com/cd/E11882_01/server.112/e10820/dynviews_3003.htm

Takže nějaká ukázka:

create table segment_test as

select rpad('A'||ROWNUM||'A',500,ROWNUM) as col from dual connect by level<1000;

A rovnou pohled V$SEGMENT_STATISTICS:

Segment statistic

V$SEGMENT_STATISTICS

A nyní spočet statistik, jak naše tabulka vypadá (ok, jsem hulvát, ale dbms_stats.gather_table.. je strašně dlouhé ;)

analyze table SEGMENT_TEST compute statistics;

A při pohledu do all_tables je vidět, že tabulka má 72 datových bloků, což dává smysl.  To jsou statistiky, které vznikly při CTASu. Takže proč to nezkusit znovu:

sqlplus / as sysdba

shutdown immediate;

startup;

Nyní V$SEGMENT_STATISTICS pro novou tabulku nevrací nic (ani prázdné řádky s nulou). Takže znovu s tím nejjednodušším:

select * from segment_test where rowid='AAATAAAABAAAVFSAAF';

A nyní pohled v V$SEGMENT_STATISTICS:

V$SEGMENT_STATISTICS - po selectu přes ROWID

V$SEGMENT_STATISTICS - po selectu přes ROWID

Jeden přístup do segmentu, jedno čtení po selectu s jedním rowid v podmínce. Tedy funguje !

P.S. Při pohledu na mé rowid je asi jasné, že jsem doma trošku prase, ale psst ;)

Written by AZOR

May 25th, 2013 at 10:04 am

Posted in Tipy na pohledy

“Obarvené sql” – DBA_HIST_COLORED_SQL

Při hledání jednoho objektu v all_objects jsem narazil na mnou neznámé view DBA_HIST_COLORED_SQL. Obarvené sql? Neznal jsem a vypadalo to dost zajímavě. Takže jsem otevřel dokumentaci, abych se s view blíže seznámil a dokumentace říká: View se váže na funkci AWR a možnost reportovat nejen TOP SQL, ale také ty, které si označíme (“obarvíme”) pomocí funkce DBMS_WORKLOAD_REPOSITORY.ADD_COLORED_SQL.

Zní docela fajn, AWR sbírá jen TOP SQL a tohle je možnost jak do AWR dostat SQL, které tam mít chceme, ale není v TOP.

Takže go, hébičky go, jdem to zkusit!

Nejprve nějaký dotaz, který bude jednoduchý, tak aby nebyl v TOP SQL a bylo na něm vidět obarvení:

select max(dummy) as from dual;

Pak zjistit jeho sql_id:

select * from v$sql s where s.sql_text like '%max(dummy)%'

Což je : ’1twnyk3cacmfw’. A přidat do sledovaných sql_id pro AWR report:

begin
dbms_workload_repository.add_colored_sql('1twnyk3cacmfw');
end;

A test:
AWR Report a obarvení sql

Tak to by bylo přidání mezi obarvená sql a nyní sebrat snapshot, spustit sql, sebrat snapshot a zjistit jestli je opravdu reportované.

declare
i int;
begin
i:=dbms_workload_repository.create_snapshot;
dbms_output.put_line('ID='||to_char(i));
end;

Spustit sql:

select max(dummy) as from dual;

A znovu snapshot

declare
i int;
begin
i:=dbms_workload_repository.create_snapshot;
dbms_output.put_line('ID='||to_char(i));
end;

A nyní ověření, že i sql, které není zcela určitě v TOP se objeví v AWR reportu:

select * from table(DBMS_WORKLOAD_REPOSITORY.AWR_SQL_REPORT_TEXT(
l_dbid=>848445615,
l_inst_num=>1,
l_bid=>893,
l_eid=>894,
l_sqlid=>'1twnyk3cacmfw'));

WORKLOAD REPOSITORY SQL Report

Snapshot Period Summary

DB Name         DB Id    Instance     Inst Num Startup Time    Release     RAC
------------ ----------- ------------ -------- --------------- ----------- ---
ORCL8          848445615 orcl8               1 24-Kvě-13 13:17 11.2.0.1.0  NO 

              Snap Id      Snap Time      Sessions Curs/Sess
            --------- ------------------- -------- ---------
Begin Snap:       893 25-Kvě-13 09:12:13        40       3.3
  End Snap:       894 25-Kvě-13 09:12:41        37       3.5
   Elapsed:                0.47 (mins)
   DB Time:                0.02 (mins)

SQL Summary                               DB/Inst: ORCL8/orcl8  Snaps: 893-894

                Elapsed
   SQL Id      Time (ms)
------------- ----------
1twnyk3cacmfw          0
Module: SQL Developer
select max(dummy) as from dual

          -------------------------------------------------------------       

SQL ID: 1twnyk3cacmfw                     DB/Inst: ORCL8/orcl8  Snaps: 893-894
-> 1st Capture and Last Capture Snap IDs
   refer to Snapshot IDs witin the snapshot range
-> select max(dummy) as from dual

    Plan Hash           Total Elapsed                 1st Capture   Last Capture
#   Value                    Time(ms)    Executions       Snap ID        Snap ID
--- ---------------- ---------------- ------------- ------------- --------------
1   2522405774                      0             1           894            894
          -------------------------------------------------------------       

Plan 1(PHV: 2522405774)
----------------------- 

Plan Statistics                           DB/Inst: ORCL8/orcl8  Snaps: 893-894
-> % Total DB Time is the Elapsed Time of the SQL statement divided
   into the Total Database Time multiplied by 100

Stat Name                                Statement   Per Execution % Snap
---------------------------------------- ---------- -------------- -------
Elapsed Time (ms)                                 0            0.4     0.0
CPU Time (ms)                                     0            0.0     0.0
Executions                                        1            N/A     N/A
Buffer Gets                                       3            3.0     0.1
Disk Reads                                        0            0.0     0.0
Parse Calls                                       1            1.0     0.4
Rows                                              1            1.0     N/A
User I/O Wait Time (ms)                           0            N/A     N/A
Cluster Wait Time (ms)                            0            N/A     N/A
Application Wait Time (ms)                        0            N/A     N/A
Concurrency Wait Time (ms)                        0            N/A     N/A
Invalidations                                     0            N/A     N/A
Version Count                                     1            N/A     N/A
Sharable Mem(KB)                                 14            N/A     N/A
          -------------------------------------------------------------       

Execution Plan
---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |       |       |     2 (100)|          |
|   1 |  SORT AGGREGATE    |      |     1 |     2 |            |          |
|   2 |   TABLE ACCESS FULL| DUAL |     1 |     2 |     2   (0)| 00:00:01 |
---------------------------------------------------------------------------

Takže pro případ, že je třeba reportovat sql v AWR, které jsou pro nás zajímavé, ale nejsou v TOP:
DBMS_WORKLOAD_REPOSITORY.ADD_COLORED_SQL,

Written by AZOR

May 25th, 2013 at 8:05 am

Posted in Tipy a triky

Tipy jak najít pain v selectu..

Potyčky s dlouhotravajícími selecty zná asi každý. Nejdůležitější je rychle a především přesně identifikovat  tu největší pain v daném selectu a začít u ní. Protože až po nalezení problémového místa může teprve přijít nějaká ta optimalizace -  přepis selectu, založení indexu, ohintování atd. Takže dnes pár tipů jak zjistit, co databáze dělá na  právě běžícím selectu a tedy jak identifikovat problémové místo či problémová místa.

Především je třeba správně  umět chápat “cost” v exekučním plánu, řádek s největším costem totiž rozhodně nemusí být problém a typicky ani není. Proč okamžitě neobvinit řádek exekučního plánu s největším costem, když nás trápí doba běhu selectu je doufám jasné a plyne to z  toho, co cost představuje. Spíš si myslím, že je třeba vysvětlit větu, proč si myslím, že tenhle to zrovna nebude. Záleží hodně na systému, v dávkových systémech, které jsem doposud potkával já tomu bylo tak, že estimátor spíše počet vrácených řádků do dalšího stupně exekučního plánu podhodnocuje než nadhodnocuje. Konkrétní  číslo, které se dá vyjet jednoduchým selectem je 2,58x. Tedy je 2,58x pravděpodobnější, že Oracle počet vrácených  řádků v exekučním plánu podhodnotí – pochopitelně v závislosti na systému, tohle je číslo jednoho konkrétního

Důvodů proč se asi člověk bude na batch systémech bude setkávát spíše s podhonocením  se asi najde několik. Obecně je tomu tak, že máme nějakou představu o datech a sloupce jsou nějakým způsobem téměř vždy korelovány,  což o proti náhodným datům a operátoru AND, kdy estimátor selectivity podmínek pronásobí opravdu spíše vede k podhodnocení. Podobně rozdělení do 4 threadu ORA_HASH(id,3) je funkce se selektivitou 25%, ale  defalutní selektivita pro funkce je 1%. Jinými slovy – záleží na systému a pokud tam programátor nesedí prvně, měl by mít nějakou představu -já by default očekávám, že další stupně exekučního plánu budou mít jako vstup počet řádků podhodnocen a tedy i cost bude menší než ve skutečnosti – a to nejspíše budou ty řádky, které budou trápit ;) Podhodnocení počtu očekávaných řádků vede logicky k použití indexu, tam kde to není úplně nejlepšejší..

A nyní tipy jak sledovat, co se tam děje:

1) Pohled v$session_longops

select * from v$session_longops where sid=&mysid order by start_time desc;

Velice známé view, která použije semtam nějaké IDE na zobrazení progressu či programátor. Zde je důležité správně hodnoty intepretovat. Především do view nejdou všechny operace, ale jen některé (dynamic sampling, spočet statistik, přístupy k objektům (Index/Table (Fast/Skip/)(Range/Full) Scany), Sorty, Hash join a pár dalších) Další věc – do view jdou operace trvající déle než 6 sekund – to znamená, že pokud Index Range Scan operace trvá v Nested loopě několik hodin, ovšem pro každou interaci se to vejde pod 6s tak v$session_longops nezobrazí nic ačkoliv dlouhotrvající Index Range Scan do tohoto view jde. Pozor na špatnou intepretaci těch nejzajímavějších sloupců sofar a totalwork (a jejich časové analogie). Protože výraz to_char(round((sofar/totalwork)*100)) ||’ %’ vypadá, že by mohl ukazovat kolik % již je hotovo. Ukazuje, ale ne však vždy – například pokud je tabulka partišnovaná a select je jen z jedné partition,  pak totalwork ukazuje počet datových bloků pro selectovanou partition v případě, že je známá v době optimalizace (static partition prunning, where x=’X'). Pokud je konkrétní partiton známá až za běhu selectu (dynamic partition pruning, where x=(select dummy from dual)) pak totalwork je průměrný počet datových bloků všech partition tabulky). Jinými slovy do totalwork mohou vstupovat statistická data, průměry i odhady, na což je třebas myslet, když je v v$session_longops řádek hotový na 178% a stále to pokračuje ;)

A těch příkladů by se našlo více, dalším jsou například dvě a více analytické funkce v projection ukazující se v exeukčním plánu stále jako jeden řádek. Sice to vypadá jako, že to trvá jeden krok (sort operace), ale v totalwork je vidět, že počet řazených bloku s každou analytickou funkcí, může růst (až dvojnásobek, podle sloupců order by) a tedy ne, neni to zadarmo ;)

Suma sumárum: jednoduché view ve kterém toho moc není a kde je třeba umět správně intepretovat  hodnoty. Co je fajn, je možnost vlastního záznamu v v$session_longops pomocí API v dbms_application_info.  Další fajn věcička je, že se tam propisují í některé dlouhotrvající tooly Oracle (backupy, přepočet statistik)

2) Pohled v$active_session_history

Tohle view je mým favoritem. View jako takové neslouží ke sledování vytížení ani běhu sql, ale obsahuje snpashoty v$session po 1 vteřině včetně toho, co zrovna daná session dělá. Stačí tedy řádky zgrupovat podle sql_plan_line_id a count(*) řádků ukazuje kolik sekund na daném řádku session trávila či ještě tráví:

select count(*),his.sql_plan_line_id, his.sql_plan_operation,his.sql_plan_options from v$active_session_history his where his.SQL_ID='sql id' and sample_time>sysdate-1 group by his.sql_plan_line_id,his.sql_plan_operation,his.sql_plan_options;

Suma sumárum: Jednoduché, krásné, efektivní. Ve většině případů dostačující. Ne moc vhodné pro sledování paralelních selectů. V$active_session_history rocks!

3) Pohled v$sql_plan_monitor

V případě, že v$active_session_history je nedostatečné, je tu ještě vyšší kalibr : v$sql_plan_monitor. View do kterého jdou SQL trvající déle než 5 sekund (neni to překlep, sem po 5s do longops 6s, dle Oracle), paralelní selecty a selecty s hintem /*+ MONITOR */. A nejdou všechny ostatní – neparalelní kratší než 5s a případně s inverzním hintem /*+ NO_MONITOR */.

select * from v$sql_plan_monitor where sql_id=‘sql_id’;

V tomhle view je vidět téměř vše co je potřeba - doba potřebná pro danou operaci, jak jdou operace za sebou, jak velké byly zprávy které si mezi sebou posílaly paralelní části, počet řádků vystupujících z daného kroku, potřebná paměť, velikost tempu pro danou operaci, počet iterací nested loopy atd.

Suma sumárum: V některých případech hůře čitelné než v$active_session_history, ale lépe se tam odhalují vnořené nested loopy a je to podstatně vhodnější pro sledování paralelních selectů. Velká nevýhoda je doba po kterou v tomto view selecty zůstávají (velice krátce – desítky minut). Nejlepšejší vychytávka: Možnost zjisti v jaké nested loop iteraci zrovna Oracle je.

4) Pohled v$sesstat

Úžasné view se spoustou statistik (pro všechny session). Dokonce tolik statistik, že pro sledování běžícího selectu je vhodné dělat pomocí CTAS:

create table actual_stats as select sid,s.statistic#,value,name,class from v$sesstat s join v$statname sp
on (s.statistic#=sp.statistic#)
where s.sid=143;

A po nějaké chvilce to odečíst, aby bylo vidět co se mění:

select sid,s.statistic#,value,name,class from v$sesstat s join v$statname sp
on (s.statistic#=sp.statistic#)
where s.sid=143;
minus select * from actual_stats;

Tohle je spíše doplňková informace pro odhalení případných podezření na operace, které nejsou na první pohled vidět a nebo na detailní rozpad.

Suma sumárum: O proti ostatním pohledum není samo o sobě vhodné pro identifikaci problému v selectu (neukazuje na kterém objektu, jaký exekuční plán apod.), nicméně pomůže v případech, které nejsou patrné v ostatních view. Typickým příkladem by mohl být chybějící index v cizím klíči – full table scan, který je nutný k dodžení referenční integrity v exekučním plánu vidět není,
ve statistikách se však objeví.

 

Tak to by bylo pro dnešek vše ;) Tipy se snad hodí.. alespoň pro některé systémy – pro OLTP se to moc nehodí ;)

Written by AZOR

April 24th, 2013 at 10:16 pm

Posted in Ladění výkonu

Doporučená literatura: Secrets of the Oracle Database

Dnes po delší odmlce alespoň tip na jednu knihu Secrets of the Oracle Database. I když velice rád mám oficiální dokumentaci, kterou má Oracle jako jednu z nejlepších - navíc nyní vylepšovanou o videa s tutoriálama a nově i s příklady. Jediné, co trošku kazí dojem je, že když vyťukáte adresu, kde by člověk čekal dokumentaci k Oracle 12c, tak je tam nehezká hláška, že beta dokumentace není pro každého..

Ale zpět ke knize Secrets of the Oracle Database - kniha je z vydavatelství Apress, což je vydavatelství, které o Oracle (a nejen o něm) vydává odborné knihy, což je takový unikát o proti tisíci knih popisující stále dokola funkci SUM() a UNION ALL.. Apress jde jinou cestou a vydává knihy, které často napsali velikánové typu Lewis, či Kyte a typicky se celá kniha věnuje jen jednomu tématu a hodně do hloubky (CBO, Indexy apod. jsou samostatné knihy).

Secrets of the Oracle Database od Norberta Debese se věnuje tomu nejzajímavějšímu – nedokumentované, skryté a tajné funkcionality Oracle. Zkryté parametry, fixed X$ pohledy, utility typu ORADEBUG atd.

Secrets of the Oracle Database

Secrets of the Oracle Database

http://www.apress.com/9781430219521

ISBN13: 978-1-4302-1952-1
Stran: 450

Written by AZOR

April 6th, 2013 at 12:41 pm

Posted in Knihovnička

Rychlotip #20 – CREATE SCHEMA

Dnešní rychlotip s číslem 20 je věnován vcelku neznámému, ale o to více užitečnému, příkazu CREATE SCHEMA.  Možná to má lehce matoucí název – nemá to relaci na vytvoření schéma jako takového a klasicky schéma je vytvořeno pomocí CREATE USER. Příkaz CREATE SCHEMA slouží k vytvoření několika objektů (tabulek, view a grantů) v jedné transakci. Což se typcky hodí při nějakém updatu systému/nasazení RFC – kdy je třeba nasadit více tabulek – pomocí CREATE SCHEMA je od Oracle zaručeno, že to proběhne “jako transakce” – tedy všechno nebo nic. Normálně je CREATE TABLE příkaz typu DDL, takže se při releasu může povéct založit jen nějaké tabulky a ostatní vyhodí chybu – což bohužel vykazuje nějaký effort na srovnaní nebo to všechno vydropovat, vylézt zpět na strom a spustit to celé znovu.

Tedy jednou větou – CREATE SCHEMA umí v jedné transakci založit více objektu v jedné transakci, konkrétně:

  • CREATE TABLE
  • CREATE VIEW
  • GRANT

Podporovaných DDL je opravdu málo a navíc neexistuje inverzní operace DROP SCHEMA, ač v SQL-1999 standard tento příkaz podporuje.

Jediné omezení je na CRETE TABLE – parallel je povoleno, ale ve skutečnosti parallně tabulky v CREATE SCHEMA nejsou zakládány a běží to seriově.

CREATE SCHEMA AUTHORIZATION dot
CREATE TABLE TEST_A (A NUMBER)
CREATE TABLE TEST_B as select 1 FROM DUAL
CREATE VIEW TEST_C as select * from all_objects
GRANT SELECT ON TEST_A TO SCOTT;

Synaxe je jednoduchá CREATE SCHEMA AUTHORIZATION <user_schema> a pak seznam tabulek, view a grantu bez středníku, středník až na konci, který zavírá statement CREATE SCHEMA.

Takže po spuštění:

SQL Error: ORA-02425: nepodařilo se vytvořit tabulku
ORA-00998: tento výraz je třeba pojmenovat alternativním jménem sloupce
02425. 00000 - "create table failed"

Protože jsem jelito a hajdalák a v TEST_B selectuji jedničku z dualu a nedal jsem tam alias, nicméně alespoň důkaz, že opravdu CREATE SCHEMA funguje a nezaložila se tabulka TEST_A ani nic jiného:

Create schema - Fail

Create schema - Fail

Takže po opravě:

CREATE SCHEMA AUTHORIZATION dot
CREATE TABLE TEST_A (A NUMBER)
CREATE TABLE TEST_B as select 1 as haf FROM DUAL
CREATE VIEW TEST_C as select * from all_objects
GRANT SELECT ON TEST_A TO SCOTT;

Je výstup následující:

schema AUTHORIZATION created.

A nyní test, že se všechno založilo i nagrantovalo:

Create schema- Success

Create schema- Success

Pro nasazovací scripty šikovná věcička, co?

Written by AZOR

March 9th, 2013 at 11:08 pm

Posted in Rychlotipy