A more general, but also more delicate parallel joining technique is based on symmetric partitioning where all participating relations are partitioned. We have encountered this method already in the discussion of the Grace hash join (figure 3.14). Symmetric partitioning splits one `big' join into several smaller and independent ones:
(9) |
The partial joins are independent from each other and can therefore be processed concurrently, i.e. in parallel. This parallelisation technique can be applied to each join algorithm that was presented in section 3.4. The Grace hash join in figure 3.14, for example, can be considered as a parallel hash join if the `for k=1 to m do' loop is parallelised, i.e. if its body is executed concurrently.
Figure 3.19 shows the structure of this family of parallel joins. It is divided into three stages:
The parallelisation, motivated by (3.6), works very well for equi-joins because it is easy to create disjoint fragments (respectively) which allow the partial joins to be independent. Unfortunately, many nonequi-joins and - as we will see in chapter 4 - many types of temporal joins cannot be divided into disjoint fragments and maintain the independence of the partial joins at the same time. One has then to decide whether to sacrifice either the disjointness or the independence with the first one being the preferable option in most cases.
The selectivities of the partial joins are much higher than for the original join because the partitioning concentrated tuples with similar values in associated fragments Rk and Qk. This is an important point in the sense that the selectivity is an important issue for the choice of the most appropriate (sequential) join algorithm for computing the partial joins . In a set of experiments that we conducted on partitioned temporal joins, for example, we observed average selectivities of 80% for the partial joins of a join .Such high figures make the nested-loop algorithm the favourable option for processing the partial joins because there will not be a large number of unnecessary tuple comparisons and, at the same time, avoids any overhead caused by sorting or hashing the data.
There are other ways of parallelising a join operation which differ from the ones presented in this section. The ones we presented are, however, the most common ones. One variation, for example, is to interleave the partitioning and joining stages similar to the case of sequential join algorithms. Further variations arise from different characteristics of the underlying parallel hardware architecture. Some parallel machines, for example, have specifically optimised communication facilities, such as broadcasts. This leads to specific cost models for this particular machine which might favour certain join strategies which are discarded when employing more general cost models. The interested reader might look at the papers that describe parallel join algorithms in detail, such as [Kitsuregawa et al., 1983], [DeWitt and Gerber, 1985], [Gerber, 1986], [Wang and Luk, 1988], [Schneider and DeWitt, 1989], [Kitsuregawa and Ogawa, 1990], [Wolf et al., 1990], [Keller and Roy, 1991] or [Wolf et al., 1993].