• Heap file • File ordinati • Indici o Hash o B+

• Heap file
• File ordinati
• Indici
o Hash
o B+-tree
• Costo delle operazioni algebriche
Simboli:
•
•
•
•
NP: numero di pagine
NR: numero record
LP: lunghezza pagina
LR: lunghezza record
Memorizzazione di una relazione
Heap: file non ordinati.
•
•
•
•
Occupazione memoria: NP = (NR*LR)/LP
Costo ricerca per chiave = NP/2 oppure NP (se la chiave è presente o no)
Costo ricerca per intervallo: σ( k1 <= k <= k2) (R) = NP
Ricerca con selezione di uguaglianza: σ( A=a) (R) = NP
Esempio: Si consideri una relazione di NR=30.000 tuple, ognuna di lunghezza LR=100 byte,
memorizzate su pagine di lunghezza LP=1024 byte. Le tuple sono indivisibili. Pertanto, il numero
di pagine necessario è pari a NP=30000*100/1024 = 3000.
Una qualsiasi ricerca quindi costa C= 3000 (1500 in media nel caso di ricerca per chiave).
File ordinato
•
•
•
•
•
Occupazione memoria: NP = (NR*LR)/LP
Costo ricerca sequenziale (per chiave) = NP/2 (caso medio)
Costo ricerca binaria (per chiave) = log(NP) (caso peggiore)1
Costo ricerca per intervallo (k1 <= k <= k2), dove K è la chiave di ordinamento: σ( k1 <= k
<= k2) (R) = log(NP) + f * NP - 1, dove f = (k1-k2)/(kmax-kmin)
Ricerca con selezione di uguaglianza: σ( A=a) = log(NP) + f * NP - 1, dove f è la
frazione di record che soddisfano il predicato di selezione
Esempio:
Una ricerca binaria costa log2(3000) = 12 accessi a pagine.
Siano Kmax=10.000, Kmin=1000, K1=300, K2=500. Il costo della ricerca per intervallo è
12+0,02*3000= 72 pagine
1
Deve essere supportato l’accesso diretto alle pagine; ciò richiede che siano memorizzate sequenzialmente
1
INDICI
Definizioni:
Un indice è una struttura dati (ausiliaria) che velocizza le ricerche per chiave (di ricerca). Esso può
essere calcolato (funzioni hash) o tabellato. In quest’ultimo caso, esso è un insieme di coppie (k,p),
dove k è un valore della chiave e p è il puntatore alla pagina che contiene il record (o i record) con
chiave k.
Un indice può essere:
• primario: l’attributo di indicizzazione è chiave (o superchiave)
• secondario: l’attributo di indicizzazione non contiene una chiave (quindi, in generale, ammette
duplicati)
• clustered: la relazione è ordinata rispetto all’attributo di indicizzazione.
Indice calcolato - FUNZIONE HASH (statico)
È una tecnica di ricerca e/o memorizzazione
L’indice può essere primario o secondario
Se usato anche per memorizzare allora è clustered
h(k) = k mod n, dove
•
•
k: codifica numerica della chiave
n: numero di pagine del file
h(k) = k mod n = ultimi logn bit di k (se n è una potenza di 2)
Problema sinonimi: più chiavi vengono assegnate alla stessa pagina – gestione dell’overflow
Indice Tabellato – B+-tree
Un B+-tree di ordine m ≥3 è un albero (ad m vie)
1.
2.
3.
4.
5.
6.
bilanciato (le foglie sono tutte allo stesso livello)
L’ordine m è il numero max di figli (puntatori) di ogni nodo non foglia;
ogni nodo non foglia, tranne la radice, ha almeno m/2 figli
se un nodo non foglia ha j valori della chiave, ha j+1 figli
i valori all’interno di un nodo sono ordinati
ogni foglia ha almeno  m/2  coppie (valore, puntatore al record), un puntatore alla foglia
successiva ed uno a quella precedente; tali coppie sono ordinate
7. Ogni chiave appare in una foglia
8. Ogni nodo è memorizzato in una pagina
ESEMPIO. Si supponga che l’attributo di indicizzazione sia lungo 9 byte e che il puntatore alle
pagine sia lungo 6 byte. Se m è l’ordine dell’albero, ogni nodo interno può contenere al massimo
(m-1)*9 chiavi e m*6 puntatori. Nell’ipotesi che una pagina sia lunga 512 byte
(m-1)*9 + m*6 <= 512
15 m <= 521
m= 34
Se ogni nodo non foglia ha m figli e l’altezza è h, allora ci sono mh-1 nodi foglia. Nella pratica, il
valore medio di figli è F minore di m (70%). Se F=100, allora un albero di altezza 4 ha più di un
milione di puntatori alle tuple. La ricerca di una tupla richiede quindi 4+1 accessi.
2
L’altezza di un albero è di norma 3-4.
ESEMPIO. Assumendo m=34 e che ogni nodo sia completo al 100%, avremo la seguente
situazione:
o LIVELLO 1: 1 nodo (radice), 33 chiavi, 34 puntatori
o LIVELLO 2: 34 nodi, 33*34=1112 chiavi, 34*34=1146 puntatori
o LIVELLO 3: 1112 nodi, 1112*33=37.026 chiavi, 1112*34 = 38.148 puntatori
o LIVELLO 4: 38.148 nodi, 1.258.884 chiavi, 1.297.032 puntatori
Una ricerca in una relazione 1.300.000 tuple costa dunque 4 accessi. Se si facesse una ricerca
binaria, nell’ipotesi di LR=100 e LP=1024, il costo sarebbe pari a circa 17 pagine.
Se l’attributo di indicizzazione della relazione R (di 30.000 tuple) dell’esempio precedente ha valori
univoci (non ammette duplicati) sono quindi necessari 3 livelli (per memorizzare 30.000 chiavi). Se
invece l’attributo ammette duplicati, potrebbero bastare meno di 3 livelli.
Se il B+-tree è un indice primario, in genere le foglie memorizzano le tuple (indice clustered).
Si noti che in tal caso, essendo le foglie riempite parzialmente, l’occupazione di memoria è
maggiore di quella che si avrebbe con una memorizzazione heap o ordinata.
Se l’indice è secondario:
o clustered: la relazione è ordinata sull’attributo di indicizzazione; ogni chiave in un nodo foglia
punta alla pagina che contiene la prima tupla con un dato valore dell’attributo
o non clustered: la relazione non è ordinata sull’attributo di indicizzazione. Siccome esistono i
duplicati, ogni puntatore delle foglie punta ad un blocco di indici che contiene i puntatori a tutte
le tuple con un dato valore della chiave.
Implementazione Operatori Relazionali con gli indici
Gli operatori dell’algebra relazionale possono essere implementati in modi diversi, a seconda del
tipo di organizzazione fisica delle relazioni coinvolte.
Selezione - Esempio: σ(A=a and B=b) (R)
1. in presenza di indici su A e/o B: si sceglie quello più selettivo per la selezione primaria; il costo
dipende da vari fattori: A è chiave primaria? Il file è ordinato rispetto ad A? Come è
implementato l’indice?.
• A è chiave (o comunque non ammette duplicati), l’indice è un B+-tree. Allora il costo è dato
dalla seguente: C=h+1
• A non è chiave (ammette duplicati), R è ordinata su A, l’indice secondario è un B+-tree
(indice di cluster) di altezza h. Allora il costo è dato dalla seguente formula: C = h+1+
sel(A=a) * pages(R)
• A è chiave (o comunque non ammette duplicati), R non è ordinata su A, l’indice secondario
è un B+-tree di altezza h. Allora il costo è dato dalla seguente formula: C = h+1
• A ammette duplicati, R non è ordinata su A, l’indice secondario è un B+-tree di altezza h.
Allora il costo è dato dalla seguente formula:C = h+1+1 + Sel(A=a)*Card(R) 
2. uso di funzione hash se definita su A o B
3
Join: R ⊗ S.
•
Nested loop con R esterna: C = Pages(R)+Pages(R)*Pages(S)
for each page r of R
transfer r in main memory
for each page s of S
transfer s in main memory
join each tuple in r with each tuple in s
•
Index nested loop: assumiamo che la condizione di join sia R.A = S.B; se esiste un indice
(ad es., B+-tree) sull’attributo di giunzione B di S, questo può essere usato per implementare
la suddetta condizione; se l’indice è di ordinamento (clustered) allora il costo è: C=
Pages(R) + n * (h+ 1+sel(B=a) * pages(R) ), dove n è la cardinalità di R ed a è un
generico valore dell’attributo A di R (per semplicità, si assume una distribuzione uniforme
dei valori di A)
for each page r of R
transfer r in main memory
for each tuple of r
let r.a be the value of the join attribute
search the first s.a through the B+-tree
scan the pages of S
for each tuple s of S with s.a
join r and s
•
SortMerge: R e S sono ordinate rispetto agli attributi di giunzione A e B. Se A è chiave
primaria di R, l’algoritmo è il seguente:
r = prima tupla di R
s = prima tupla di S
while (r != null and s !=null)
if r[A] = s[B]
{aggiungi <r, s> al risultato
s+;}
else if r[A] < s[B] r++
else s++
Il costo è C= Pages(R)+ Pages(S)
ESEMPIO. La relazione IMP ha un indice secondario B+-tree sull’attributo Dip. La relazione DIP
ha un indice primario hash sull’attributo codice.
IMP ha 10.000 tuple memorizzate su 2.000 pagine.
DIP ha 125 tuple memorizzate su 13 pagine.
Il B+-tree ha 3 livelli.
Ogni DIP ha in media 10.000/125=80 IMP.
IMP non è ordinato su Dip. Quindi il B+-tree ha un ulteriore livello che contiene i blocchi di
puntatori
Costi del join:
4
1)
2)
3)
4)
nested loop, IMP X DIP C = 2000+(13*2000) = 28.000 pagine
nested loop, DIP X IMO, C = 13+(13*2000) = 26.013
Uso hash su DIP con IMP esterno C = 2.000 + 10.000 = 12.000
Uso B+tree su IMP con DIP esterno C = 13 + 125(3+1 + 80) = 10.500
5