|
@@ -0,0 +1,191 @@
|
|
|
+% !TEX root = ../main.tex
|
|
|
+\subsection{Query a}
|
|
|
+
|
|
|
+\paragraph{Piano di accesso logico della query a}
|
|
|
+\begin{center}
|
|
|
+ \begin{forest}
|
|
|
+ [{$\pi^{b}$ e.Titolo, sw.Url}
|
|
|
+ [{$\bowtie$ e.IdEdizione = sw.IdEdizione}
|
|
|
+ [{$\sigma$e.Titolo $>=$'G' $\wedge$ e.Titolo $<$ 'H'}
|
|
|
+ [Edizioni e]
|
|
|
+ ]
|
|
|
+ [SitiWeb sw]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ \end{forest}
|
|
|
+\end{center}
|
|
|
+
|
|
|
+\paragraph{Piano di accesso fisico della query a senza indici}
|
|
|
+\begin{center}
|
|
|
+ \begin{forest}
|
|
|
+ [{Project(\{e.Titolo, sw.Url\})}
|
|
|
+ [{SortMerge(e.IdEdizione = sw.IdEdizione)}
|
|
|
+ [{Sort(\{e.IdEdizione\})}
|
|
|
+ [{Project(\{e.Titolo, e.IdEdizione\})}
|
|
|
+ [{Filter(e.Titolo $>=$ 'G' AND e.Titolo $<$ H)}
|
|
|
+ [{TableScan(Edizioni e)}]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ [{Sort(\{sw.IdEdizione\})}
|
|
|
+ [{Project(\{sw.Url, sw.IdEdizione\})}
|
|
|
+ [{TableScan(SitiWeb sw)}]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ \end{forest}
|
|
|
+\end{center}
|
|
|
+
|
|
|
+\paragraph{Piano di accesso fisico della query a con due indici}
|
|
|
+\begin{center}
|
|
|
+ \begin{forest}, baseline, qtree
|
|
|
+ [{Project(\{e.Titolo, sw.Url\})}
|
|
|
+ [{IndexNestedLoop(e.IdEdizione = sw.IdEdizione)}
|
|
|
+ [{IndexFilter(Edizioni e, IndETit,\\ e.Titolo $>=$ 'G' AND e.Titolo $<$ H)}]
|
|
|
+ [{IndexFilter(SitiWeb sw, IndSWIdEd,\\ e.IdEdizione = sw.IdEdizione)}]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ \end{forest}
|
|
|
+\end{center}
|
|
|
+Indici necessari: \texttt{IndETit} (indice della tabella Edizioni sull’attributo Titolo) e \texttt{IndSWIdEd} (indice della tabella SitiWeb sulla chiave IdEdizione).
|
|
|
+
|
|
|
+\subsection{Query b}
|
|
|
+\paragraph{Piano di accesso logico della query b}
|
|
|
+\begin{center}
|
|
|
+ \begin{forest}
|
|
|
+ [{$\tau$(\{$-$TempoTotaleLettura\})}
|
|
|
+ [{$\pi^{b}$ v.IdUtente, SUM(v.TempoLettura) TempoTotaleLettura}
|
|
|
+ [{$\sigma$ SUM(v.TempoLettura) $>$ 10}
|
|
|
+ [{\{v.IdUtente\} $\gamma$ \{SUM(v.TempoLettura)\}}
|
|
|
+ [{$\sigma$ v.TempoLettura $<$ 60}
|
|
|
+ [{Visite v}]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ \end{forest}
|
|
|
+\end{center}
|
|
|
+L’output dell’operatore $\gamma$ è già proiettato sulle sole dimensioni di analisi e risultati delle
|
|
|
+funzioni di aggregazione, non occorrerebbe proiettare su \texttt{\{v.IdUtente, SUM(v.TempoLettura)\}}; lo faccio per poter rinominare in TempoTotaleLettura il risultato della SUM.
|
|
|
+
|
|
|
+Nella $\tau$, l’ordinamento discendente è reso dal segno `$-$' per convenzione (in questo caso comunque il tipo è numerico).
|
|
|
+
|
|
|
+\paragraph{Piano di accesso fisico della query b senza indici}
|
|
|
+\begin{center}
|
|
|
+ \begin{forest}
|
|
|
+ [{Sort(\{$-$TempoTotaleLettura\})}
|
|
|
+ [{Project(\{v.IdUtente, SUM(v.TempoLettura) TempoTotaleLettura\})}
|
|
|
+ [{Filter(SUM(v.TempoLettura) $>$ 10)}
|
|
|
+ [{GroupBy(\{v.IdUtente\}, \{SUM(v.TempoLettura)\})}
|
|
|
+ [{Sort(\{v.IdUtente\})}
|
|
|
+ [{Project(\{v.IdUtente, v.TempoLettura\})}
|
|
|
+ [{Filter(v.TempoLettura $<$ 60)}
|
|
|
+ [{TableScan(Visite v)}]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ \end{forest}
|
|
|
+\end{center}
|
|
|
+
|
|
|
+\clearpage
|
|
|
+\paragraph{Piano di accesso fisico della query b con indici}
|
|
|
+\begin{center}
|
|
|
+ \begin{forest}, baseline, qtree
|
|
|
+ [{Sort(\{$-$TempoTotaleLettura\})}
|
|
|
+ [{Project(\{v.IdUtente, SUM(v.TempoLettura) TempoTotaleLettura\})}
|
|
|
+ [{GroupBy(\{v.IdUtente\}, \{SUM(v.TempoLettura)\})}
|
|
|
+ [{\sout{Project(\{v.IdUtente, v.TempoLettura\})}}
|
|
|
+ [{IndexFilter(Visite v, IndVIdUt, v.TempoLettura $<$ 60)}
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ \end{forest}
|
|
|
+\end{center}
|
|
|
+Indice necessario: \texttt{IndVIdUt} (indice della tabella Visite sull’attributo IdUtente).
|
|
|
+
|
|
|
+Non occorre ordinare prima di raggruppare: l’output di IndexFilter è già ordinato sull’insieme di attributi dell’indice (in questo caso \texttt{\{v.IdUtente\}}), che coincide nel nostro caso con l’insieme delle dimensioni di analisi.
|
|
|
+
|
|
|
+Non occorre nemmeno proiettare su \texttt{\{v.IdUtente, v.TempoLettura\}} prima del raggruppamento, in quanto la groupby può ricevere il record direttamente dalla IndexFilter e scartare gli attributi non rilevanti (cioè quelli che non sono dimensione di analisi né input delle funzioni di aggregazione).
|
|
|
+\vfill
|
|
|
+\subsection{Query c}
|
|
|
+\paragraph{Piano di accesso logico della query c}
|
|
|
+\begin{center}
|
|
|
+ \begin{forest}, baseline, qtree
|
|
|
+ [{$\pi$ a.IdArticolo, a.Titolo, COUNT(*) NumeroVisite,\\SUM(v.TempoLettura) TempoTotaleLettura}
|
|
|
+ [{$\sigma$ COUNT(*) $>=$ 3}
|
|
|
+ [{\{a.IdArticolo, a.Titolo\} $\gamma$ \{COUNT(*), SUM(v.TempoLettura)\}}
|
|
|
+ [{$\bowtie$ a.IdArticolo = v.IdArticolo}
|
|
|
+ [{$\sigma$ a.Premium = 'N'}
|
|
|
+ [{Articoli a}]
|
|
|
+ ]
|
|
|
+ [{Visite v}]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ \end{forest}
|
|
|
+\end{center}
|
|
|
+\clearpage
|
|
|
+\paragraph{Piano di accesso fisico della query c senza indici}
|
|
|
+\begin{center}
|
|
|
+ \begin{forest}, baseline, qtree
|
|
|
+ [{Project(\{a.IdArticolo, a.Titolo, COUNT(*) NumeroVisite,\\SUM(v.TempoLettura) TempoTotaleLettura\})}
|
|
|
+ [{Filter(COUNT(*) $>=$ 3)}
|
|
|
+ [{GroupBy(\{a.IdArticolo, a.Titolo\}, \{COUNT(*), SUM(v.TempoLettura)\})}
|
|
|
+ [{SortMerge(a.IdArticolo = v.IdArticolo)}
|
|
|
+ [{Sort(a.IdArticolo)}
|
|
|
+ [{Project(\{a.IdArticolo, a.Titolo\})}
|
|
|
+ [{Filter(a.Premium = 'N')}
|
|
|
+ [{TableScan(Articoli a)}]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ [{Sort(v.IdArticolo)}
|
|
|
+ [{Project(\{v.IdArticolo, v.TempoLettura\})}
|
|
|
+ [{TableScan(Visite v)}]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ \end{forest}
|
|
|
+\end{center}
|
|
|
+L’output di SortMerge è già ordinato per a.IdArticolo e, dato che \texttt{a.IdArticolo $\to$ a.Titolo},
|
|
|
+non occorre ordinare prima della groupby.
|
|
|
+
|
|
|
+\paragraph{Piano di accesso fisico della query c con due indici}
|
|
|
+\begin{center}
|
|
|
+ \begin{forest}, baseline, qtree
|
|
|
+ [{Project(\{a.IdArticolo, a.Titolo, COUNT(*) NumeroVisite,\\SUM(v.TempoLettura) TempoTotaleLettura\})}
|
|
|
+ [{Filter(COUNT(*) $>=$ 3)}
|
|
|
+ [{GroupBy(\{a.IdArticolo, a.Titolo\}, \{COUNT(*), SUM(v.TempoLettura)\})}
|
|
|
+ [{IndexNestedLoop(a.IdArticolo = v.IdArticolo)}
|
|
|
+ [{Project(\{a.IdArticolo, a.Titolo\})}
|
|
|
+ [{IndexFilter(Articoli a,\\ IndAIdA, a.Premium = 'N')}
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ [{Project(\{v.IdArticolo, v.TempoLettura\})}
|
|
|
+ [{IndexFilter(Visite v,\\IndVIdA, v.IdArticolo = a.IdArticolo)}]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ \end{forest}
|
|
|
+\end{center}
|
|
|
+Indici necessari: IndAIdA (indice della tabella Articoli sull’attributo IdArticolo), IndVIdA (indice
|
|
|
+della tabella Visite sull’attributo IdArticolo).
|
|
|
+Non occorre fare un ordinamento sull’output della IndexNestedLoop: avendo ricevuto input
|
|
|
+ordinato su IdArticolo dalla IndexFilter, e sapendo che \texttt{a.IdArticolo $\to$ a.Titolo}, l’input
|
|
|
+della groupby è già raggruppato per le dimensioni di analisi.
|