Queer European MD passionate about IT

piani_di_accesso.tex 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. % !TEX root = ../main.tex
  2. \subsection{Query a}
  3. \paragraph{Piano di accesso logico della query a}
  4. \begin{center}
  5. \begin{forest}, baseline, qtree
  6. [{$\pi^{b}$ r.IdRicetta , r.Nome}
  7. [{$\bowtie$ p.IdPersona = r.IdCreatrice}
  8. [{$\sigma$ p.Nome = 'Giovanni'}
  9. [Persone p]
  10. ]
  11. [Ricette r]
  12. ]
  13. ]
  14. \end{forest}
  15. \end{center}
  16. Non c'è in questo caso differenza tra $\pi^{b}$ e $\pi$: non ci possono essere
  17. duplicati.
  18. \paragraph{Piano di accesso fisico della query a senza indici}
  19. \begin{center}
  20. \begin{forest}, baseline, qtree
  21. [{Project(\{r.IdRicetta , r.Nome\})}
  22. [{SortMerge(p.IdPersona = r.IdCreatrice)}
  23. [{Sort([p.IdPersona])}
  24. [{Project(\{p.IdPersona\})}
  25. [{Filter(p.Nome = 'Giovanni')}
  26. [{TableScan(Persone p)}]
  27. ]
  28. ]
  29. ]
  30. [{Sort([r.IdCreatrice])}
  31. [{Project(\{r.IdRicetta, r.Nome, r.IdCreatrice\})}
  32. [{TableScan(Ricette r)}]
  33. ]
  34. ]
  35. ]
  36. ]
  37. \end{forest}
  38. \end{center}
  39. \paragraph{Piano di accesso fisico della query a con due indici}
  40. \begin{center}
  41. \begin{forest}, baseline, qtree
  42. [{Project(\{r.IdRicetta , r.Nome\})}
  43. [{IndexNestedLoop(p.IdPersona = r.IdCreatrice)}
  44. [{IndexFilter(Persone p,\\ IndPN, p.Nome = 'Giovanni')}]
  45. [{IndexFilter(Ricette r,\\IndRC, r.IdCreatrice = p.IdPersona)}]
  46. ]
  47. ]
  48. \end{forest}
  49. \end{center}
  50. Indici necessari: \texttt{IndPN} (indice della tabella Persone sull’attributo
  51. Nome) e \texttt{IndRC} (indice della tabella Ricette sull'attributo Creatrice).
  52. \clearpage
  53. \subsection{Query b}
  54. \paragraph{Piano di accesso logico della query b}
  55. \begin{center}
  56. \begin{forest}, baseline, qtree
  57. [{$\tau$[-DiversiFornitori]}
  58. [{$\pi^{b}$ fa.IdBirrificio, COUNT(DISTINCT fa.IdFornitore) DiversiFornitori}
  59. [{$\sigma$ COUNT(DISTINCT fa.IdFornitore) $>=$ 3}
  60. [\{fa.IdBirrificio\} {$\gamma$ \{COUNT(DISTINCT fa.IdFornitore)\}}
  61. [{$\sigma$ fa.Data $>=$ '2020-01-01'}
  62. [Fatture fa]
  63. ]
  64. ]
  65. ]
  66. ]
  67. ]
  68. \end{forest}
  69. \end{center}
  70. Non c'è in questo caso differenza tra $\pi^{b}$ e $\pi$: non ci possono essere
  71. duplicati, in quanto la GROUP BY raggruppa per IdBirrificio.
  72. \paragraph{Piano di accesso fisico della query b senza indici}
  73. \begin{center}
  74. \begin{forest}, baseline, qtree
  75. [{Sort[-DiversiFornitori]}
  76. [{Project(\{fa.IdBirrificio, COUNT(DISTINCT fa.IdFornitore) DiversiFornitori\})}
  77. [{Filter(COUNT(DISTINCT fa.IdFornitore) $>=$ 3)}
  78. [{GroupBy(\{fa.IdBirrificio\}, \{COUNT(DISTINCT fa.IdFornitore)\})}
  79. [{Sort([fa.IdBirrificio])}
  80. [{Filter(fa.Data $>=$ '2020-01-01')}
  81. [{TableScan(Fatture fa)}]
  82. ]
  83. ]
  84. ]
  85. ]
  86. ]
  87. ]
  88. \end{forest}
  89. \end{center}
  90. Il sort sull'attributo dimensione di analisi prima della GroupBy è necessario,
  91. in quanto non è garantito che i record della tabella Fatture siano raggruppati
  92. per IdBirrificio.
  93. Lo sarebbero se l'organizzazione primaria della tabella fosse sequenziale
  94. proprio su questo attributo, il che è estremamente poco probabile.
  95. \clearpage
  96. \paragraph{Piano di accesso fisico della query b con un indice}
  97. \begin{center}
  98. \begin{forest}, baseline, qtree
  99. [{Sort[-DiversiFornitori]}
  100. [{Project(\{fa.IdBirrificio, COUNT(DISTINCT fa.IdFornitore) DiversiFornitori\})}
  101. [{Filter(COUNT(DISTINCT fa.IdFornitore) $>=$ 3)}
  102. [{GroupBy(\{fa.IdBirrificio\}, \{COUNT(DISTINCT fa.IdFornitore)\})}
  103. [{Sort([fa.IdBirrificio])}
  104. [{IndexFilter(Fatture fa, IndFD, fa.Data $>=$ '2020-01-01')}]
  105. ]
  106. ]
  107. ]
  108. ]
  109. ]
  110. \end{forest}
  111. \end{center}
  112. Indice necessario: \texttt{IndFD} (indice della tabella Fatture sull’attributo
  113. Data).
  114. Il sort sull'attributo IdBirrificio prima della GroupBy è necessario, in quanto
  115. i record in input sono ordinati per data, il che non ci garantisce che siano
  116. raggruppati per IdBirrificio (che è dimensione di analisi).
  117. \subsection{Query c}
  118. \paragraph{Piano di accesso logico della query c}
  119. \begin{center}
  120. \begin{forest}, baseline, qtree
  121. [{$\pi^{b}$ fo.RagioneSociale, SUM(fa.Importo) ImportoTotale, AVG(fa.Importo) ImportoMedio}
  122. [$\sigma$ SUM(fa.Importo) $>$ 10
  123. [{\{fo.IdFornitore, fo.RagioneSociale\} $\gamma$ \{SUM(fa.Importo), AVG(fa.Importo)\}}
  124. [{$\bowtie$ fa.IdFornitore = fo.IdFornitore}
  125. [{Fornitori fo}]
  126. [{$\bowtie$ fa.IdBirrificio = b.IdBirrificio}
  127. [{$\sigma$ b.Nome = 'Pirati Rossi'}
  128. [{Birrifici b}]
  129. ]
  130. [{Fatture fa}]
  131. ]
  132. ]
  133. ]
  134. ]
  135. ]
  136. \end{forest}
  137. \end{center}
  138. In questo caso non ci dovrebbe essere differenza tra $\pi^{b}$ e $\pi$: non ci
  139. devono essere due fornitori con la stessa ragione sociale (la ragione sociale
  140. è chiave naturale); è comunque possibile un errore di inserimento se non ho
  141. impostato un vincolo di unicità anche su questo attributo, che non ho scelto
  142. come chiave primaria della tabella.
  143. \clearpage
  144. \paragraph{Piano di accesso fisico della query c senza indici}
  145. \begin{center}
  146. \begin{forest}, baseline, qtree
  147. [{Project(\{fo.RagioneSociale,\\SUM(fa.Importo) ImportoTotale, AVG(fa.Importo) ImportoMedio\})}
  148. [{Filter(SUM(fa.Importo) $>$ 10)}
  149. [{GroupBy(\{fo.IdFornitore,fo.RagioneSociale\}, \{SUM(fa.Importo), AVG(fa.Importo)\})}
  150. [{MergeSort(fa.IdFornitore = fo.IdFornitore)}
  151. [{Sort([fo.IdFornitore])}
  152. [{Project(\{fo.IdFornitore,\\fo.RagioneSociale\})}
  153. [{Fornitori fo}]
  154. ]
  155. ]
  156. [{Sort([fa.IdFornitore])}
  157. [{Project(\{fa.IdFornitore, fa.Importo\})}
  158. [{MergeSort(fa.IdBirrificio = b.IdBirrificio)}
  159. [{Sort([b.IdBirrificio])}
  160. [{Project(\{b.IdBirrificio\})}
  161. [{Filter(b.Nome = 'Pirati Rossi')}
  162. [{TableScan(Birrifici b)}]
  163. ]
  164. ]
  165. ]
  166. [{Sort([fa.IdBirrificio])}
  167. [{Project(\{fa.IdBirrificio,\\fa.IdFornitore fa.Importo\})}
  168. [{Fatture fa}]
  169. ]
  170. ]
  171. ]
  172. ]
  173. ]
  174. ]
  175. ]
  176. ]
  177. ]
  178. \end{forest}
  179. \end{center}
  180. \clearpage
  181. \paragraph{Piano di accesso fisico della query c con due indici}
  182. \begin{center}
  183. \begin{forest}, baseline, qtree
  184. [{Project(\{fo.RagioneSociale,\\SUM(fa.Importo) ImportoTotale, AVG(fa.Importo) ImportoMedio\})}
  185. [{Filter(SUM(fa.Importo) $>$ 10)}
  186. [{GroupBy(\{fo.IdFornitore,fo.RagioneSociale\}, \{SUM(fa.Importo), AVG(fa.Importo)\})}
  187. [{MergeSort(fa.IdFornitore = fo.IdFornitore)}
  188. [{Sort([fo.IdFornitore])}
  189. [{Project(\{fo.IdFornitore,\\fo.RagioneSociale\})}
  190. [{Fornitori fo}]
  191. ]
  192. ]
  193. [{Sort([fa.IdFornitore])}
  194. [{Project(\{fa.IdFornitore, fa.Importo\})}
  195. [{IndexNestedLoop(fa.IdBirrificio = b.IdBirrificio)}
  196. [{IndexFilter(Birrifici b, IndBN,\\b.Nome = 'Pirati Rossi')}]
  197. [{IndexFilter(Fatture fa, IndFIdB,\\fa.IdBirrificio = b.IdBirrificio)}]
  198. ]
  199. ]
  200. ]
  201. ]
  202. ]
  203. ]
  204. ]
  205. \end{forest}
  206. \end{center}
  207. Indici necessari: \texttt{IndBN} (indice della tabella Birrifici sull’attributo
  208. Nome) e \texttt{IndFIdB} (indice della tabella Fatture sull'attributo
  209. IdBirrificio).