270 likes | 401 Vues
Organizace a zpracování dat I. Dynamické metody. Rozšiřitelné hašování (Fagin). K lokalizaci stránek s daty využívá adresář. Připouští jak přidávání, tak odebírání záznamů. K získání dat stačí 1-2 přístupy na disk.
E N D
Organizace a zpracování dat I Dynamické metody
Rozšiřitelné hašování (Fagin) • K lokalizaci stránek s daty využívá adresář. • Připouští jak přidávání, tak odebírání záznamů. • K získání dat stačí 1-2 přístupy na disk. • Neumí se vypořádat se situací, kdy pro příliš mnoho různých klíčů je hašovaná hodnota totožná.
Rozšiřitelné hašování - schéma 2 3 000 001 3 010 011 3 100 101 110 1 111
Rozšiřitelné hašování – schéma (2) 2 3 3 000 001 3 010 011 100 2 101 110 111 2
Rozšiřitelné hašování – schéma (3) 2 4 3 0000 0001 0010 4 0011 0100 0101 4 0110 0111 1000 2 1001 1010 1011 2 1100 1101 1110 1111
Rozšiřitelné hašování – pomocné funkce • GetPage(pt,pg) – čte stránku z adresy pt do vyrovnávací paměti pg. • Collision-Act – ošetřuje kolizi/nenalezení záznamu
Rozšiřitelné hašování - Access procedure Access(var pt:pgadr; var index:integer; k:key; var found:bool); var pg:page; b:hashkey; begin b:=h(k); pt:=directory[brbr-1…br-d+1]; index:=bt+sbt+s+1…bt+1; GetPage(pt,pg); if pg.body[index].dk = k then begin found:=true; returnend; Collision-Act(pg,index,k,found); end;
Rozšiřitelné hašování - Insert procedure Insert(r:drec; var ok:Bool); var index,j,k:integer; found:Bool; pt,pt1:pgadr; buffer,pg,pg1:page; begin Access(pt,index,r.dk,found); if found then ok:=false; returnend; GetPage(pt,pg); ifnot IsFree(pg) thenbegin buffer:=pg; pg.LocD:=pg.LocD+1; pg1.LocD:=pg.LocD; Clean(pg); for i:=1 to m do Insert1(buffer.body[i],pg,pg1); Insert1(r,pg,pg1); Indicate(pt,j,k); for i:=j to k do directory[i]:=pt1; PutPage(pt1,pg1); endelse Insert1(r,pg,pg); ok:=true; PutPage(pt,pg); end;
Rozšiřitelné hašování - vlastnosti • Nalezení záznamu vyžaduje 2 přístupy na disk • Adresář bývá možné držet ve vnitřní paměti (pak je jen 1 přístup na disk) • Lze zrychlit provádění aktualizací při dávkovém zpracování: požadavky setřídit dle hašované hodnoty, a pak postupovat jako při aktualizaci setříděných sekvenčních souborů
Lineární hašování – Litwin, 1980 • Stránky je možné štěpit po pevném počtu vložení záznamů • Předpokládá se hašovací funkce h(K), která pro libovolný klíč vrátí binární celé číslo v dostatečném rozsahu
Lineární hašování – postupné štěpení stánek expanze expanze
Lineární hašování - GetLinAddr FUNCTION GetLinAddr(K:Key):BlockAddr; VAR w, a : Integer; BEGIN w:=log2(pages+1) ; a:=h(K) mod 2w; IF a pages THEN a:=a mod 2w+1; return a END;
Lineární hašování - dokončení • Aneb: stačí využít vhodný počet dolních bitů z hašovaného klíče. • Při štěpení stránky rozdělujeme záznamy dle (w-1)-ního bitu: ty s ‚0‘ zůstávají, ty s ‚1‘ jdou do nové stránky. • Pozor! Musí se zpracovat i záznamy ze stránky přetečení!!
Skupinové štěpení stránek • Stránky štěpeny po určitém počtu přidaných záznamů do souboru • Snaha o rovnoměrnější rozdělení záznamů do stránek než u lineárního hašování • Soubor dělený do s skupin po g stránkách • Skupiny se při štěpení přerozdělují do g+1 stránek
Skupinové štěpení stránek (2) • Předpoklad: Existence posloupnosti nezávislých hašovacích funkcí h0,h1,… : K<0,g> FUNCTION PgAddr(k:key,d,sp:integer):integer; VAR j,s,x: integer; BEGIN x:=hash(k); s:=s0; FOR j:=0 TO d-1 DO BEGIN x:=x mod s + hj(k)*s; s:=s*(g+1)/g END; IF x mod s < sp THEN x:=x mod s+hd(k)*s; PgAddr:=x END;
Skupinové štěpení stránek • Algoritmus přístupu k datům simuluje umístění záznamu v průběhu celého postupu štěpení stránek. • Lineární (Litwinovo) hašování je skupinovým štěpením stránek pro g=1.
Stromy • Asi nejčastější dynamická datová na vnějších pamětech s přímým přístupem. • Orientovaný graf je složený z uzlů a hran – uspořádaných dvojic uzlů. • Každý uzel má konečnou množinu uzlů - (bezprostředních) následníků / potomků a množinu uzlů zvaných předchůdci či rodiče. • Strom je orientovaný graf, kdy každý uzel kromě jednoho má právě jednoho rodiče. Uzel bez rodiče se nazývá kořen stromu, uzly bez potomků nazýváme listy.
B-strom B-strom (řádu m) je rozvětvený výškově vyvážený strom splňující tato omezení: • kořen má nejméně dva potomky, není-li listem • každý uzel kromě kořene a listů má nejméně m/2 a nejvýše m potomků • každý uzel má nejméně m/2 - 1 a nejvíce m-1 datových záznamů • všechny větve jsou stejně dlouhé
B-strom (2) • data v uzlu jsou organizována takto: p0,(k1,p1,d1),(k2,p2,d2),…,(kn,pn,dn),u kde pi jsou ukazatelé na potomky, ki klíče, di data a u nevyužitý prostor • záznamy (ki,pi,di) jsou uspořádány vzestupně dle klíčů
B-strom - modifikace • kořen podstromu může rozdělovat klíče v uzlech podstromu neostře (strom pak nazýváme redundantní - na původní verzi se budeme odkazovat jako na neredundantní), což dovolí i následující úpravy: • data mohou být uložena pouze v listech - v nelistových uzlech jsou pouze klíče • data mohou být uložena odděleně - na poslední úrovni pak ukazatelé neukazují na další uzly stromu, ale na data
B-strom - příklad Neredundantní B-strom (2-3-strom)
B-strom - struktury • Pro neredundantní variantu s daty v uzlech můžeme použít tyto struktury: TYPE rec = RECORD p:PgAdr; k:Key; d:Data END; page = RECORD m : Integer; {zaplnění stránky} leaf : Boolean; {je to list?} body : ARRAY [1..MaxM] OF rec; END;
B-strom – struktury (2) • Pro rekurzivní variantu s daty v uzlech je třeba použít variantní strukturu: TYPE irec = RECORD p:PgAdr; k:Key; END; drec = RECORD k:Key; d:Data END;
B-strom – struktury (3) • Také je třeba si pamatovat celou větev ve stromě (přinejmenším pro vkládání a vypouštění): TYPE Branch = RECORD h:integer; PgPtr: ARRAY [1..hmax] OF PgAdr; Ind: ARRAY [1..hmax] OF Integer; END;
B-strom - Access PROCEDURE Access(root:PgAdr; k:Key; VAR s:Branch; VAR found:Boolean); VAR pt:PgAdr; i:Integer; BEGIN s.h:=0; pt:=root; IF root=NIL THEN BEGIN found:=false; Exit END; REPEAT s.h:=s.h+1; s.ptr[s.h]:=pt; GetPage(pt,pg); Search(pg,k,found,i,pt); s.ind[s.h]:=i UNTIL pg.leaf END;
B-strom - Insert PROCEDURE Insert(VAR root:PgAdr; r:rec; VAR ok:Boolean); VAR wr:rec; wk:Key; pt:PgAdr; p1,p2:page; found:Boolean; s:Branch; i:Integer; BEGIN IF root=NIL THEN InitRoot(root,s) ELSE BEGIN Access(root,r.k,s,found); IF found THEN BEGIN ok:=false; Exit END END; ok:=true; wr:=r; GetPage(s.ptr[s.h],p1);
B-strom – Insert (2) FOR i:=s.h DOWNTO 1 DO WITH p1 DO BEGIN IF m<MaxM THEN BEGIN MemIns(p1,wr,s.ind[i]); Exit END; Split(p1,wr,p2,pt); IF i=1 THEN BEGIN NewRoot(p1,p2,root,pt); Exit END; wk:=body[m].k; GetPage(s.ptr[i-1],p1); body[s.ind[i-1]].k:=wk; wr.k:=p2.ibody[p2.m].k; wr.p:=pt END; END;