These and other advantages of the invention will be apparent to those of ordinary skill in the art by reference to the following detailed description and the accompanying drawings.
To efficiently share computations of window-based join operators, the invention is a new method for sharing join queries with different window constraints and filters. The two key ideas of the invention are: state-slicing and pipelining. The window states of the shared join operator are sliced into fine-grained pieces based on the window constraints of individual queries. Multiple sliced window join operators, with each joining a distinct pair of sliced window states, can be formed. Selections now can be pushed down below any of the sliced window joins to avoid unnecessary computation and memory usage shown above. However, N2 joins appear to be needed to provide a complete answer if each of the window states were to be sliced into N pieces. The number of distinct join operators needed would then be too large for a data stream management system DSMS to hold for a large N. We This hurdle is overcome by elegantly pipelining the slices. This enables building a chain of only N sliced window joins to compute the complete join result. This also enables to selectively share a subsequence of such a chain of sliced window join operators among queries with different window constraints.
Based on the inventive state-slice sharing, two algorithms are proposed for the chain buildup, one that minimizes the memory consumption and the other that minimizes the CPU usage. The algorithms are guaranteed to always find the optimal chain with respect to either memory or CPU cost, for a given query workload. Experimental results show that the invention provides the best performance over a diverse range of workload settings among alternate solutions in the literature.
State-Sliced One-Way Window Join
For purposes of the ensuing description, the following equivalent join operator notations are used: is equivalent to |x,
is equivalent to x|,
is
equivalent to
is equivalent to
is equivalent to
, and is equivalent to x.
A one-way sliding window join of streams A and B is denoted as A[W]|xB
where stream A has a sliding window of size W. The output of the join consists of all pairs of tuples a ε A, b ε B, such that Tb−Ta<W, and tuple pair (a,b) satisfies the join condition.
where stream A has a sliding window of range: Wend−Wstart. The start and end window are Wstart and Wend respectively. The output of the join consists of all pairs of tuples a ε A, b ε B, such that Wstart≦Tb−Ta<Wend, and (a,b) satisfies the join condition.
We can consider the sliced one-way sliding window join as a generalized form of the regular one-way window join. That is
The diagram 40
are shown by the diagram 50 in
The semantics of the state-sliced window join require the checking of both the upper and lower bounds of the time-stamps in every tuple probing step. In
The start window of the first join in a chain is 0. For any adjacent two joins, Ji and Ji+1, the start window of Ji+1 equals the end window of prior Ji (0≦i<N) in the chain. Ji and Ji+1 are connected by both the Purged-A-Tuple output queue of Ji as the input A stream of Ji+1, and the Propagated-B-Tuple output queue of Ji as the input B stream of Ji+1.
The diagram 60 of
Table 2 below depicts an example execution of this chain. We assume that one single tuple (an a or a b ) will only arrive at the start of each second, w1=2 sec, w2=4 sec and every a tuple will match every b tuple (Cartesian Product semantics). During every second, an operator will be selected to run. Each running of the operator will process one input tuple. The content of the states in J1 and J2, and the content in the queue between J1 and J2 after each running of the operator are shown in Table 2.
Execution in Table 2 follows the steps in
We observe that the union of the join results of J1:
is equivalent to the results of a regular sliding window join:
The order among the joined results is restored by the merge union operator. To prove that the chain of sliced joins provides the complete join answer, we first introduce the following lemma.
in a chain, at the time that one b tuple finishes the cross-purge step, but not yet begins the probe step, we have: (1) ∀a ε A::[Wi−1,Wi]Wi−1≦Tb−Ta<Wi; and (2) ∀a tuple in the input steam A, Wi−1≦Tb−Ta<Wi
a ε A::[Wi−1,Wi]. Here A::[Wi−1,Wi] denotes the state of stream A.
Proof: (1). In the cross-purge step (
(2We use a proof by contradiction. If a≠A::[Wi−1,Wi], then first we assume a ε A::[Wj−,Wj],j<i. Given Wi−1≦Tb−Ta, we know Wj≦Tb−Ta. Then a cannot be inside the state A::[Wj−1,Wj]since a would have been purged by b when it is processed by the join operator
We got a contradiction. Similarly a cannot be inside any state A::[Wk−1,Wk], k>i. pt]0pt1.3expt]1.3ex0pt
is equivalent to the results of a regular one-way sliding window join A[WN]|×B.
Proof: Lemma 1(1) shows that the sliced joins in a chain will not generate a result tuple (a,b) with Ta−Tb>W. That is, ∀(a,b) ε Å1≦i≦N A[Wi−1,Wi]|s×B
(a,b) ε A[W]|×B.
We need to show:
at a certain time. Lemma 1(2) shows that tuple a would be inside the state of A[Wi−1,Wi] at that same time. Then
From Lemma 1, we see that the state of the regular one-way sliding window join A[W]|×B is distributed among different sliced one-way joins in a chain. These sliced states are disjoint with each other in the chain, since the tuples in the state are purged from the state of the previous join. This property is independent from operator scheduling, be it synchronous or even asynchronous.
State-Sliced Binary Window Join
Similar to Definition 1, we can define the binary sliding window join. The definition of the chain of sliced binary joins is similar to Definition 2 and is thus omitted for space reasons. The diagram 70 of
where stream A has a sliding window of range: WAend−WAstart and stream B has a window of range WBend−WBstart. The join result consists of all pairs of tuples a ε A, b ε B, such that either WAstart≦Tb−Ta<WAend or WBstart≦Ta−Tb<WBend, and (a,b) satisfies the join condition.
The execution steps for sliced binary window joins can be viewed as a combination of two one-way sliced window joins. Each input tuple from stream A or B will be captured as two reference copies, before the tuple is processed by the first binary sliced window join1. The copies can be made by the first binary sliced join. One reference is annotated as the male tuple (denoted as am) and the other as the female tuple (denoted as af). The execution steps to be followed for the processing of a stream A tuple by
are shown by the diagram 80 of
Intuitively the male tuples of stream B and female tuples of stream A are used to generate join tuples equivalent to a one-way join:
The male tuples of stream A and female tuples of stream B are used to generate join tuples equivalent to the other one-way join:
Note that using two copies of a tuple will not require doubled system resources since: (1) the combined workload (in
is equivalent to the results of a regular sliding window join A[WN]×B[WN].
Using Theorem 1, we can prove Theorem 2. Since we can treat a binary sliced window join as two parallel one-way sliced window joins, the proof is fairly straightforward.
We now show how the proposed state-slice sharing can be applied to the running example introduced above to share the computation between the two queries. The shared plan is depicted by the diagram 90 of and
The purged tuples from the states of
are sent to
as input tuples. The selection operator σ4 filters the input stream A tuples for
The selection operator σA filters the joined results of
for Q2. The predicates in σA and σA are both A.value>Threshold.
Compared to alternative sharing approaches discussed in the background of the invention section, the inventive state-slice sharing method offers significant advantages. Selection can be pushed down into the middle of the join chain. Thus unnecessary probings in the join operators are avoided. The routing cost is saved. Instead a pre-determined route is embedded in the query plan. States of the sliced window joins in a chain are disjoint with each other. Thus no state memory is wasted.
Using the same settings as previously, we now calculate the state memory consumption Cm and the CPU cost Cp for the state-slice sharing paradigm as follows:
The first item of Cm corresponds to the state memory in; the second to the state memory in
. The first item of Cp is the join probing cost of
; the second the filter cost of σA; the third the join probing cost of
; the fourth the cross-purge cost; while the fifth the union cost; the sixth the filter cost of σA. The union cost in Cp is proportional to the input rates of streams A and B. The reason is that the male tuple of the last sliced join
acts as punctuation for the union operator. For example, the male tuple a1f is sent to the union operator after it finishes probing the state of stream B in
, indicating that no more joined tuples with timestamps smaller than a1f will be generated in the future. Such punctuations are used by the union operator for the sorting of joined tuples from multiple join operators.
Comparing the memory and CPU costs for the different sharing solutions, namely naive sharing with selection pull-up (Eq. 1), stream partition with selection push-down (Eq. 2) and state-slice chain (Eq. 3), the savings of using the state slicing sharing are:
with Cm(i) denoting Cm, Cp(1) denoting Cp in Equation i (i=1,2,3); and window ratio
Compared to sharing alternatives discussed in the background section above, the inventive state-slice sharing achieves significant savings. As a base case, when there is no selection in the query plans (i.e., S94 =1), state-slice sharing will consume the same amount of memory as the selection pullup while the CPU saving is proportional to the join selectivity S. When selection exists, state-slice sharing can save about 20%-30% memory, 10%-40% CPU over the alternatives on average. For the extreme settings, the memory savings can reach about 50% and the CPU savings about 100%. The actual savings are sensitive to these parameters. Moreover, from Eq. 4 we can see that all the savings are positive. This means that the state-sliced sharing paradigm achieves the lowest memory and CPU costs under all these settings. Note that we omit λ in Eq. 4 for CPU cost comparison, since its effect is small when the number of queries is only 2. The CPU savings will increase with increasing λ, especially when the number of queries is large.
Turning now to the consideration of how to build an optimal shared query plan with a chain of sliced window joins. Consider a data stream management system DSMS with N registered continuous queries, where each query performs a sliding window join A[wi]B[wi] (1≦i≦N) over data streams A and B. The shared query plan is a DAG with multiple roots, one for each of the queries.
Given a set of continuous queries, the queries are first sorted by their window lengths in ascending order. Two processes are proosed for building the state-slicing chain in that order memory-optimal state-slicing and CPU-optimal state-slicing. The choice between them depends on the availability of the CPU and memory in the system. The chain can also first be built using one of the algorithms and migrated towards the other by merging or splitting the slices at runtime.
Memory-Optimal State-Slicing
Without loss of generality, we assume that wi<wi+1 (1≦i<N). Let's consider a chain of the N sliced joins: J1, J2, . . . , JN, with Ji as
(1≦i≦N, w0=0). A union operator Ui is added to collect joined results from J1, . . . , Ji for query Qi (1<i≦N), as shown by diagram 100 of
is equal to the state memory used by the regular sliding window join: A[wN]B[wN].
Proof: From Lemma 1, the maximum timestamp difference of tuples (e.g., A tuples) in the state of Ji is (wi−wi−1), when continuous tuples from the other stream (e.g., B tuples) are processed. Assume the arrival rate of streams A and B is denoted by λA and λB respectively. Then we have:
Let's again use the count of comparisons per time unit as the metric for estimated CPU costs. Comparing the execution (
Comparing to the alternative sharing methods noted above in the Background of the Invention, we notice that the Memory-Optimal chain may not always win since it requires CPU cost for: (1) (N−1) more times of purging for each tuple in the streams A and B; (2) extra system overhead for running more operators; and (3) CPU cost for (N−1) union operators. In the case that the selectivity of the join S is rather small, the routing cost in the selection pull-up sharing may be less than the extra cost of the Mem-Opt chain. In short, the Mem-Opt chain may not be the CPU-optimal solution for all settings.
CPU-Optimal State-Slicing
We hence now discuss how to find the CPU-Optimal state-slice sharing (CPU-Opt) which will yield minimal CPU costs. We notice that the Mem-Opt state-slice sharing may result in a large number of sliced joins with very small window ranges each. In such cases, the extra per tuple purge cost and the system overhead for holding more operators may not be capable of being neglected.
In
Both the shared query plans in
The difference of CPU costs in these scenarios comes from the purge cost (the first item), the routing cost (the second item) and the system overhead (the third item). The system overhead mainly includes the cost for moving tuples in/out of the queues and the context change cost of operator scheduling. The system overhead is proportional to the data input rates and number of operators.
Considering a chain of N sliced joins, all possible merging of sliced joins can be represented by edges in a directed graph G={V,E}, where V is a set of N+1 nodes and E is a set of
edges. Let ∀vi ε V(0≦i≦N) represent the window wi of Qi (w0=0). Let the edge ei,j from node vi to node vj (i<j) represent a sliced join with start-window as wi and end-window as wj. Then each path from the node v0 to node vN represents a variation of the merged state-slice sharing, as shown by the diagram 120 in
Similar to the above calculation of Cp(a) and Cp(b), we can calculate the CPU cost of the merged sliced window joins represented by every edge. We denote the CPU cost ei,j of the sliced join as the length of the edge li,j. We have the following lemma.
Based on Lemma 2, we can apply the principle of optimality here and transform the optimal state-slice problem to the problem of finding the shortest path from v0 to vN in an acyclic directed graph. Using the well-known Dijkstra 's algorithm, we can find the CPU-Opt query plan in O(N2), with N being the number of the distinct window constraints in the system. Even when we incorporate the calculation of the CPU cost of the
edges, the total time for getting the CPU optimal state-sliced sharing is still O(N2).
In case the queries do not have selections, the CPU-Opt chain will consume the same amount of memory as the Mem-Opt chain. With selections, the CPU-Opt chain may consume more memory.
Online Migration of the State-Slicing Chain
Online migration of the shared query plan is important for efficient processing of stream queries. The state-slicing chain may need maintenance when: (1) queries enter or leave the system, (2) queries update predicates or window constraints, and (3) runtime statistic collection invokes plan adaptation.
The chain migration is achieved by two primitive operation: merging and splitting of the sliced join. For example when query Qi (i<N) leaves the system, the corresponding sliced join
could be merged with the next sliced join in the chain. Or if the corresponding sliced join had been merged with others in the CPU-Opt chain, splitting of the merged join may be invoked first.
Online splitting of the sliced join Ji can be achieved by: (1) stopping the system execution for Ji; (2) updating the end window of Ji to w′i; (3) inserting a new sliced join J′i with window [w′i,wi] to the right of Ji and connecting the query plan; and (4) resuming the system. The queue between Ji and J′i is empty right after the insertion. The execution of Ji will purge tuples, due to its new smaller window, into the queue between Ji and J′i and eventually fill up the states of J′i correctly.
Online merging of two adjacent sliced joins Ji and Ji+1 requires the queues between these two joins empty. This can be achieved by scheduling the execution of Ji+1 after stopping the scheduling of Ji. Once the queue between Ji and Ji+1 is empty, we can simply (1) concatenate the corresponding states of Ji and Ji+1; (2) update the end window of Ji to wi+1; (3) remove Ji+1 from the chain; and (4) resume the system.
The overhead for chain migration corresponds to constant system cost for operator insertion/deletion. The system suspending time during join splitting is neglectable, while during join merging it is bounded by the execution time needed to empty the queue in-between. No extra processing costs arise in either case.
Push Selections into Chain
When the N continuous queries each have selections on the input streams, we aim to push the selections down into the chain of sliced joins. For clarity of discussion, we focus on the selection push-down for predicates on one input stream. Predicates on multiple streams can be pushed down similarly. We denote the selection predicate on the input stream A of query Qi as σi and the condition of σi as condi.
Mem-Opt Chain with Selection Push-Down
The selections can be pushed down into the chain of sliced joins as shown by the diagram 130 in
cond′i=condi v condi+1 v . . . v condN
Logically each tuple may be evaluated against the same selection predicate for multiple times. In the actual execution, we can evaluate the predicates (cond1, 1≦i≦N) in the decreasing order of i for each tuple. As soon as a predicate (e.g. condk) is satisfied, stop further evaluating and attach k to the tuple. Thus this tuple can survive until the k th slice join and no further. Similar to Theorem 3, we have the following theorem.
Intuitively the total state memory consumption is minimal since that: (1) each join probe performed by in
CPU-Opt Chain with Selection Push-Down
The merging of adjacent sliced joins with selection push-down can be achieved following the scheme shown in
Similarly to the CPU optimization discussed above with respect to the CPU-optimal state-slicing, the Dijkstra's algorithm can be used to find the CPU-Opt sharing plan with minimized CPU cost in O(N2) Such CPU-Opt sharing plan may not be Memory-Optimal.
In summary, window-based joins are stateful operators that dominate the memory and CPU consumptions in a data stream management system DSMS. Efficient sharing of window-based joins is a key technique for achieving scalability of a DSMS with high query workloads. The invention is a new method for efficiently sharing of window-based continuous queries in a DSMS. By slicing a sliding window join into a chain of pipelining sliced joins, the inventive method results in a shared query plan supporting the selection push-down, without using an explosive number of operators. Based on the state-slice sharing, two algorithms are proposed for the chain buildup, which achieve either optimal memory consumption or optimal CPU usage.
The present invention has been shown and described in what are considered to be the most practical and preferred embodiments. The inventive state-slice method can be extended to distributed systems, because the properties of the pipelining sliced joins fit nicely in the asynchronous distributed system. Also, when the queries are too many to fit into memory, combining query indexing with state-slicing is a possibility. That departures may be made there from and that obvious modifications will be implemented by those skilled in the art. It will be appreciated that those skilled in the art will be able to devise numerous arrangements and variations which, although not explicitly shown or described herein, embody the principles of the invention and are within their spirit and scope.
This application claims the benefit of U.S. Provisional Application No. 60/807,220, entitled “State-Slice: New Paradigm of Multi-Query Optimization of Window-Based Stream Queries”, filed on Jul. 13, 2006, the contents of which is incorporated by reference herein.
Number | Date | Country | |
---|---|---|---|
60807220 | Jul 2006 | US |