La soluzione più banale al problema consiste nell’avere una scoring function $S$ che restituisce un punteggio in funzione dei valori della tupla.
to_be_sorted=[]fortupleinR:# compute S for each tupleto_be_sorted.append({tuple,S(tuple)})# sort based on S value and return the first k valuesreturnto_be_sorted.sort().head(k)
❗
questo approccio e estremamente costoso in quanto prevede il
soffrono rispettivamente di escludere elementi con prezzo di poco maggiore ma un numero di chilometri estremamente basso (near-miss) e l’altra di dare in output tutti i veicoli di un dato modello (information overload)
Per implementare l’operatore top-sort e sufficiente allocare un buffer $B$ che contenga le $k$ tuple, ad ogni tupla letta la si confronta con la $k$-esima già nel buffer e la si scarta se non maggiore
ℹ️
se una tupla non e maggiore dell’ultima migliore $k$-esima si presume non fara parte del risultato finale
se non si ha nessun indice non c’e’ altra soluzione che applicare l’operatore di top-sort
Se si può sfruttare un indice sull’attributo di selezione (clausola WHERE) allora la situazione migliora ma dipende dalla selettività della selezione
❗
senza selezione si sta nella merda….
Cosa possiamo fare se avessimo un indice sugli attributi di ranking?, come dovrebbe essere l’indice?
analizziamo la geometria :)
Se si plottano le tuple in un grafo basato sugli attributi di scoring si ottiene che le tuple che soddisfano la top-$k$ query si trovano tutte sotto una data linea
si considera di cercare macchine con i parametri di scoring più bassi possibili
Si può generalizzare a un punto qualunque dello spazio $q$, in questo caso si ottiene che i punti che soddisfano la top-$k$ query sono quelli all’interno di una regione di spazio intorno al punto di query $q$
Di conseguenza il problema delle top-$k$ query si riduce al problema di trovare i $k$ nearest neighbors rispetto al query point $q$
Di conseguenza il problema può essere modellato come segue, dato il seguente modello
uno spazio $D$-dimensionale formato dagli attributi di scoring $A = (A_1,A_2,...,A_D)$
una relazione $R(A_1,A_2,...,R_1,R_2,....)$
un query point $q = (q_1,q_2,..,q_D)$
una funzione $d: A \times A \rightarrow \Re$ che misura la distanza fra due punti di $A$
Il problema diventa:
dati un punto $q$ una relazione $R$, un intero $k \geq 1$ e una funzione distanza $d$ determinare le $k$ tuple in $R$ che sono le più vicine a $q$ secondo $d$
Una possibilità per risolvere le query top-$k$ e quello di usare b+tree multiattributo
, questa soluzione non e ottimale. e molto meglio usare indici multidimensionali come i r-tree
ℹ️
i b+tree multi-attributo mostrano gli stessi problemi che si hanno in caso di
Determinare se un nodo contiene foglie utili: $d_{MIN}$ limite
#
Per determinare se un nodo dell’albero deve essere considerato in fase di ricerca si definisce la distanza del nodo come la distanza della foglia più vicina al punto di ricerca $q$
$$
d_{MIN}(q,Reg(N)) = inf\{d(q,p) | P \in Reg(N)\}
$$
Di conseguenza si ha che se il nodo $N$ contiene punti interessanti deve essere vero che $d_{MIN}$ deve essere inferiore del raggio di ricerca $r$
Risolvere le query top-$k$: algoritmo knnoptimal
#
Per risolvere le query con il modello sopracitato si introduce l’algoritmo KNNOptimal, l’algoritmo scandisce l’albero considerando i nodi $d_{MIN}(q,Reg(N)) < r$ e memorizza la tupla $t$ con $d(q,t)$ minore
# query point inputq={}# Initialize pq with [ptr(rn),0];PQ=[]PQ.append({ptr(RN),0})rNN=10000000;whilePQ.len()!=0:N=get_distance_and_point(PQ.pop())# read page from diskRead(N)ifNisleaf:fortinN:ifd(q,t)<rNN:# save tuple for resultresult=t# update search radiusrNN=d(q,t)# update queueupdate(PQ)else:forNcinN:ifdMIN(q,Reg(Nc))<rNN:ENQUEUE(PQ,[ptr(Nc),dMIN(q,Reg(Nc))])returnresult,rNN
L’algoritmo KNNOptimal e corretto e I/O-ottimale in quanto accede solo pagine in cui e possibile trovare foglie vicine al risultato
Non e detto che l’algoritmo KNNOptimal
restituisca tuple concordi con il parametro di filtering, per supportare la casistica si utilizza una variante del KNNOptimal
con supporto al distance browsing
Nella coda PQ si includono anche le tuple e l’algoritmo termina quando il primo elemento della coda e una tupla
Author
Matteo Longhi
I’m a software engineer with a passion for Music, food, dogs, videogames and open source software, i’m currently working as a devops engineer
Tecnologie progettazione basi di dati -
This article is part of a series.