|
Therefore, it is very important that:
|
|
for ( each tuple s ∈ S ) do
{
for ( each tuple r ∈ R ) do
{
if ( r(Y) == s(Y) )
{
output (r, s);
}
}
}
|
Worst case performance:
# Disk I/O = T(S) × T(R)
|
Advantage:
|
|
|
Open( )
{
R.Open( );
S.Open( );
s = S.getNext(); // s = current tuple of S
}
|
Graphically:
|
Note:
|
getNext( ) algorithm in pseudo code:
/* ------------------------------------------------------------------
getNext( ): output the next (just 1 !!!) tuple in the join R ⋈ S
----------------------------------------------------------------- */
getNext( )
{
/* ==============================================================
Note: s already has the current (next ?) tuple of relation S
============================================================== */
while ( true )
{
// Loop exits when:
// 1. we found a tuple ∈ R that joins with s
// 2. R ⋈ S is done (returns NotFound)
/* =================================================
Get the next tuple r ∈ R to Join
================================================ */
r = R.getNext(); // Get next tuple in R to perform Join
if ( r == NotFound )
{ /* ---------------------------------------------------
Tuple s has joined with every tuple ∈ R
Use next tuple ∈ S in the Join
--------------------------------------------------- */
s = S.getNext( );
if ( s == NotFound )
{
/* ***********************************
We have processed the last tuple ∈ S
********************************** */
return NotFound; // Done !!!
}
/* ===========================================
We have a new tuple s ∈ S
Restart R from the beginning
=========================================== */
R.Close(); // Close first
R.Open( ); // Reset R to beginning
r = R.getNext(); // Get current tuple in R
}
/* =================================================
When we reach here, we have:
s = current tuple in S for the Join operation
r = current tuple in R for the Join operation
================================================ */
if ( r(Y) == s(Y) )
{
return (r,s); // Return next tuple of Join
}
// Repeat and try the next tuple in R
}
}
|
Close( )
{
R.Close( );
S.Close( );
}
|
|
|
|
while ( S ≠ empty )
{
Read M - 1 blocks of S:
organize these tuples into a search structure
(e.g., hash table)'
Rewind R;
while ( R ≠ empty )
{
Read 1 block (b) of R;
for ( each tuple t ∈ block b ) do
{
Find the tuples s1, s2, ... of S (in the search structure)
that join with t
Output (t,s1), (t,s2), ...
}
}
}
|
Graphically:
|
(1) The algorithm will read S once:
# disk I/Os = B(S)
(2) # fragments Si read: B(S)/(M−1) times
For each fragment Si, algorithm read R once
# disk I/Os = B(S)/(M−1) × B(R)
|
|
(Presented previously !!!)
(1) The algorithm will read S once:
# disk I/Os = B(S)
(2) # fragments Si read: B(S)/(M−1) times
For each fragment Si, algorithm read R once
# disk I/Os = B(S)/(M−1) × B(R)
|
(Presented previously !!!)
(1) The algorithm will read R once:
# disk I/Os = B(R)
(2) # fragments Ri read: B(R)/(M−1) times
For each fragment Ri, algorithm read S once
# disk I/Os = B(R)/(M−1) × B(S)
|