[DMDB] Fix issues, improve query processing with notes on time complexities

This commit is contained in:
2026-07-27 14:41:27 +02:00
parent d197d01f24
commit be2e079959
22 changed files with 142 additions and 34 deletions
@@ -13,4 +13,6 @@
\EndProcedure
\end{algorithmic}
\end{algorithm}
Here, the max output size is $T_R \cdot T_S$, where $T_X$ is the number of tuples for realtion $X$.
Here, the max output size is $T_R \cdot T_S$, where $T_X$ is the number of tuples for relation $X$.
The cost is obviously \cost{$\texttt{cnt}(R) \cdot \texttt{cnt}(S)$}, with $\texttt{cnt}(X)$ the number of tuples in $X$.
@@ -13,5 +13,5 @@
\end{algorithmic}
\end{algorithm}
The cost here is $P_R + P_R \cdot P_S$ I/Os, where $P_X$ is the number of pages in the relation $X$.
The cost here is \cost{$P_R + P_R \cdot P_S$ I/Os}, where $P_X$ is the number of pages in the relation $X$.
Furthermore, the DBMS should put the smaller relation on the outer loop to improve performance.
@@ -13,7 +13,7 @@
\end{algorithmic}
\end{algorithm}
The cost here is $P_R + T_R \cdot C(I_S)$ I/Os, with $P_X$ the number of pages in the relation $X$, $T_X$ the number of tuples in said relation
The cost here is \cost{$P_R + T_R \cdot C(I_S)$ I/Os}, with $P_X$ the number of pages in the relation $X$, $T_X$ the number of tuples in said relation
and $C(I_X)$ is the cost to probe the index $I_X$ of relation $X$ and depends on the clustering of data and type of index.
This operation needs three buffer frames. $1$ for $R$, $1$ for output and $1$ to traverse $I_S$
@@ -16,7 +16,7 @@
We have $B$ buffer frames, of which one is reserved for the pages of $S$ and one is reserved for the output, thus the $B - 2$ blocks.
Each of these blocks houses $P_R / (B - 2))$ pages of $R$, reducing search costs by only scanning $S$ once for every block.
The cost here is $P_R + (P_R / (B - 2) \cdot P_S$ I/Os.
The cost here is \cost{$P_R + (P_R / (B - 2) \cdot P_S$ I/Os}.
If however, $R$ fits into memory, we have cost $P_R + P_S$ I/Os.
We can reduce that further by building as second step (right after the first for loop) a in-memory hash table for the tuples in the $R$ pages block.
This reduces the cost of comparisons, however, we need $(B - 2) \cdot f$ memory now.
@@ -14,7 +14,7 @@
\end{algorithmic}
\end{algorithm}
The cost here is $P_R + T_R \cdot C(I_S)$ I/Os.
The cost here is \cost{$P_R + T_R \cdot C(I_S)$ I/Os}.
We sort the tuples in each buffer frame on the predicate key, which leads to tuples in $R$ with the same key only requiring a single index search.
In addition, tuples with ``similar'' values in $R$ will likely match with keys on the same pages of $I_S$, which will already be in the buffer pool.
@@ -2,11 +2,11 @@
We first sort $R$ and $S$ on the join attributes with external merge sort (see Section~\ref{sec:external-sort}). We then read the sorted files and merge.
This is of course not great for performance, but if the relations are already sorted, we can skip the first step.
The cost (if there are \bi{no duplicates}) is $\texttt{Sort}(S) + \texttt{Sort}(R) + P_R + P_S$ I/Os.
The cost (if there are \bi{no duplicates}) is \cost{$\texttt{Sort}(S) + \texttt{Sort}(R) + P_R + P_S$ I/Os}.
If there are duplicates (i.e. the keys are not unique, say we are joining on a column that doesn't have the UNIQUE constraint)
then we need to move the pointer for the join back on the second relation to make sure we don't miss any tuples.
The cost now of course isn't linear anymore and worst case quadratic, $\tco{\texttt{Sort}(S) + \texttt{Sort}(R) + P_R \cdot P_S}$.
The cost now of course isn't linear anymore and worst case quadratic, \cost{$\tco{\texttt{Sort}(S) + \texttt{Sort}(R) + P_R \cdot P_S}$}.
Compared to BNLJ, its performance doesn't depend on the amount of memory available, but tends to be a tad slower than BNLJ, if BNLJ is provided with ample memory.
@@ -1,10 +1,10 @@
\subsubsection{Optimized Sort Merge Join ((O)SMJ)}
In this section, we are exploring how we can optimize sort and merge with extra memory.
Sorting can be optimized using replacement sort, the output is $\frac{P_R + P_S}{2B}$ sorted runs of length $2B$.
Sorting can be optimized using replacement sort, the output is \cost{$\frac{P_R + P_S}{2B}$} sorted runs of length $2B$.
That of course means that the logical optimization is to do a $K$-way merge to merge the sorted runs and join the relations at the same time.
If we have $B$ frames, so we can do a $B-1$ way merge, otherwise, we merge runs from each relation separately to reduce the number of runs
until we have less than $B$ sorted runs, then we perform the join.
The cost drops to $3 \cdot (P_R + P_S)$ I/Os, but we need memory such that $B^2 \geq \max\{ P_R, P_S \}$
The cost drops to \cost{$3 \cdot (P_R + P_S)$ I/Os}, but we need memory such that $B^2 \geq \max\{ P_R, P_S \}$
@@ -20,4 +20,4 @@ The benefit of this approach is that in the third step, we are only operating on
What we ideally do in the above algorithm is to do \textit{recursive partitioning}, i.e. as already \textit{somewhat} described, we partition each partition again,
if it has more than one page. This further reduces access times.
The cost for this is $3 \cdot (P_S + P_R)$, thus both OSMJ and PHJ are very similar in performance.
The cost for this is \cost{$3 \cdot (P_S + P_R)$}, thus both OSMJ and PHJ are very similar in performance.