From ff5667d7aa014bd4dfc47ebedeef2cfcda74fb45 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 24 Oct 2019 01:06:06 -0400 Subject: [PATCH] SLides --- src/teaching/cse-662/2019fa/index.md | 4 +- .../2019fa/slide/2019-10-24-Cayuga.erb | 792 +++++ .../graphics/2019-10-24-CayugaExample.svg | 474 +++ .../graphics/2019-10-24-CayugaUnannotated.svg | 372 ++ .../graphics/2019-10-24-CayugaUpdates.svg | 464 +++ .../slide/graphics/2019-10-24-DFAExample.svg | 480 +++ .../slide/graphics/2019-10-24-NDFAExample.svg | 430 +++ .../slide/graphics/2019-10-24-PubSub.svg | 2979 +++++++++++++++++ .../cse-662/2019fa/slide/graphics/DB.png | Bin 0 -> 16335 bytes 9 files changed, 5993 insertions(+), 2 deletions(-) create mode 100644 src/teaching/cse-662/2019fa/slide/graphics/2019-10-24-CayugaExample.svg create mode 100644 src/teaching/cse-662/2019fa/slide/graphics/2019-10-24-CayugaUnannotated.svg create mode 100644 src/teaching/cse-662/2019fa/slide/graphics/2019-10-24-CayugaUpdates.svg create mode 100644 src/teaching/cse-662/2019fa/slide/graphics/2019-10-24-DFAExample.svg create mode 100644 src/teaching/cse-662/2019fa/slide/graphics/2019-10-24-NDFAExample.svg create mode 100644 src/teaching/cse-662/2019fa/slide/graphics/2019-10-24-PubSub.svg create mode 100644 src/teaching/cse-662/2019fa/slide/graphics/DB.png diff --git a/src/teaching/cse-662/2019fa/index.md b/src/teaching/cse-662/2019fa/index.md index 50af0353..70f29d54 100644 --- a/src/teaching/cse-662/2019fa/index.md +++ b/src/teaching/cse-662/2019fa/index.md @@ -104,8 +104,8 @@ After the taking the course, students should be able to: * **Oct 10** - Skyserver (continued) * **Oct 15** - NoDB / RAW ([paper 1](https://dl-acm-org.gate.lib.buffalo.edu/citation.cfm?id=2213864) | [paper 2](http://www.vldb.org/pvldb/vol7/p1119-karpathiotakis.pdf)) * **Oct 17** - Group Presentations -* **Oct 22** - Legorithmics ([paper](https://infoscience.epfl.ch/record/186017/files/main-final.pdf)) -* **Oct 24** - Streaming ([paper](https://www.cs.cornell.edu/johannes/papers/2007/2007-CIDR-Cayuga.pdf)) +* **Oct 22** - Legorithmics ([paper](https://infoscience.epfl.ch/record/186017/files/main-final.pdf) | [slides](slides/2019-10-22-Legorithmics.html)) +* **Oct 24** - Streaming ([paper](https://www.cs.cornell.edu/johannes/papers/2007/2007-CIDR-Cayuga.pdf) | [slides](slides/2019-10-24-Cayuga.html)) * **Oct 29** - Scan Sharing ([paper](https://dl-acm-org.gate.lib.buffalo.edu/citation.cfm?id=1687707)) * **Oct 31** - Group Presentations * **Nov 4** - Differential Dataflow ([paper](http://cidrdb.org/cidr2013/Papers/CIDR13_Paper111.pdf)) diff --git a/src/teaching/cse-662/2019fa/slide/2019-10-24-Cayuga.erb b/src/teaching/cse-662/2019fa/slide/2019-10-24-Cayuga.erb index 0d62715c..e4103411 100644 --- a/src/teaching/cse-662/2019fa/slide/2019-10-24-Cayuga.erb +++ b/src/teaching/cse-662/2019fa/slide/2019-10-24-Cayuga.erb @@ -3,3 +3,795 @@ template: templates/cse662_2019_slides.erb title: Cayuga date: October 24 --- + +
+
+

Non-Standard Database Workloads

+
+
Stock Markets
+
Alert me when a stock reverses a downward trend.
+
Manufacturing IoT
+
Alert me when two adjacent process steps both signal non-critical errors.
+
Cloud Computing
+
Alert me when the number of errors is more than twice as high as the 2-week average.
+
+
+ +
+ + + + + + + +
Classical DB
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
These ProblemsClassical DB
Expressive QueriesExpressive Queries
Changing DataStatic Data🗶
Static QueriesAd-Hoc Queries
Latency: MsecLatency: Sec/Min🗶
+
+ + +
+ + + + + + + + + +
+
🗶
+
Classical DBPublish/Subscribe
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
These ProblemsPub/Sub
Expressive QueriesFilter Queries🗶
Changing DataChanging Data
Static QueriesStatic Queries
Latency: MsecLatency: Msec
+ +
+ +
+

Trivial

+

+

Expressive

+
+ +
+

Trivial

+

+

Performant Expressiveness

+

+

Expressive

+
+ +
+

Cayuga

+
+
+
Language
+
Maximize Expressiveness w/o Compromising Performance
+
+ +
+
Compiler
+
Emit a tight, optimized program representation
+
+ +
+
Runtime
+
Necessary support for concurrent, asynchronous execution
+
+
+
+ +
+ +
+
+

Language

+ +

Start with something familiar

+
+ +
+
+
Projection, Selection, Union
+
Single-pass operators: Easy to do efficiently
+
Join
+
Multi-pass operator: Will need to revisit
+
Aggregate
+
Single-pass operator: Probably ok
+
Blocking operator: Not ok
+
+
+ +
+

Projection

+

+                          SELECT A, B, C, ... 
+                          FROM [Query]
+    
+ +

Emit tuples emitted by [Query] with only columns A, B, C

+
+ +
+

Selection

+

+                    FILTER { [Condition] } [Query]
+    
+

Emit only tuples emitted by [Query] that pass [Condition]

+
+ +
+

Union

+

+                        [Query1] UNION [Query2]
+    
+

Emit any tuples emitted by either [Query1] or [Query2]

+
+
+ +
+
+

Join

+ +
    +
  1. $O(N^2)$ complexity doesn't work when $N = \infty$
  2. +
  3. Storage requirements grow infinitely
  4. +
  5. Work per tuple grows with every insertion
  6. +
+ +

How to fix?

+
+ +
+
+
+
RHS tuple has to arrive after LHS tuple
+
Storage requirement only scales in LHS complexity
+
+
+
Each LHS tuple joins at most one RHS tuple
+
$O(N^2) \rightarrow O(N)$
+
Better chance of work staying constant
+
+
+
+ +
+

Join (Next)

+

+                 [Query1] NEXT { [Condition] } [Query2]
+    
+
    +
  1. For each tuple emitted by [Query1],
  2. +
  3. wait until [Query2] emits a tuple that passes [Condition]
  4. +
  5. and emit the cartesian product of the tuples
  6. +
+
+
+ +
+
+

Aggregate

+ +

+ Blocking operators are not ok. Need semantics that allow tuples to be emitted sooner. +

+ +
+ +
+

Group-by...ish Aggregates

+
    +
  • When do you create a new group?
  • +
  • Which tuples go into the group?
  • +
  • When does the group get emitted?
  • +
+
+ +
+

Aggregate (Fold)

+

+      [Query1] FOLD { [Condition1], [Condition2], [Agg] } [Query2]
+    
+
    +
  1. For each tuple emitted by [Query1]
  2. +
  3. Wait until [Query2] emits a tuple that passes [Condition1]
  4. +
  5. Update [Agg]
  6. +
  7. Emit the cartesian product of the [Query1] tuple, the first [Query2] tuple, and the [Agg] value
  8. +
  9. If the [Query2] tuple ALSO passes [Condition2] repeat from 2
  10. +
+
+ +
+

Analogous to...

+

+      [Query1] NEXT { [Condition1] } [Query2]
+               NEXT { [Condition1] } [Query2] 
+               NEXT { [Condition1] } [Query2] 
+               NEXT { [Condition1] } [Query2] 
+               ... until [Condition2] is failed
+    
+
+
+ +
+ +
+

Cayuga

+
+
+
Language
+
Maximize Expressiveness w/o Compromising Performance
+
+ +
+
Compiler
+
Emit a tight, optimized program representation
+
+ +
+
Runtime
+
Necessary support for concurrent, asynchronous execution
+
+
+
+ +
+

Deterministic Finite Automata

+ +

Model a program by a directed graph

+ +
    +
  • Each node is a state
  • +
  • Each edge is a transition with a rule
  • +
  • One node is a start state
  • +
  • One node is an end state
  • +
+
+ +
+

Deterministic Finite Automata

+ +

The program accepts an input: A string.

+
    +
  1. Start at the start state.
  2. +
  3. Find the transition edge corresponding to the next character and follow it.
  4. +
  5. Repeat from 2 until the end state of end of string
  6. +
  7. Accept the string if the final state is the end state
  8. +
+
+ +
+ +

/Hi+!/ ↣ + "Hi!" + "OHiiiiii!" + "Ha!"

+
+ +
+

Deterministic Finite Automata

+ +
    +
  • Simple
  • +
  • Easy to implement efficiently
  • +
  • Expressive (Regular Expressions)
  • +
+ +

... but what if we don't know which edge to take?

+
+ +
+

Nondeterministic Finite Automata

+ +

The program state is a set of active states

+ +
    +
  1. Start in state $\{\texttt{start}\}$
  2. +
  3. Initialize the next state to $\{\}$
  4. +
  5. For each active state, follow each transition edge with a matching letter and add the destination to the active states in the next step
  6. +
  7. Replace the current state with the next state.
  8. +
  9. Repeat from 2 until the end state is active or there are no active states
  10. +
  11. Accept the string if the end state is active
  12. +
+
+ +
+ +

/Ha?i!+/ ↣ + "Hi!" + "OHai!" + "HaHai!" + "HiHaH!" +

+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LetterStart$S_1$$S_2$$S_3$End
H
i
H
a
H
!
+
+ +
+

Nondeterministic Finite Automata

+
    +
  • Nearly as simple
  • +
  • Almost as easy to implement efficiently
  • +
  • Expressive (Full Regular Expressions)
  • +
+

NDFAs can be compiled down to DFAs

+
+
+ +
+ +
+

Cayuga

+
+
+
Language
+
Maximize Expressiveness w/o Compromising Performance
+
+ +
+
Compiler
+
Emit a tight, optimized program representation
+
+ +
+
Runtime
+
Necessary support for concurrent, asynchronous execution
+
+
+
+ +
+

Cayuga Autometa

+

Each node of the NDFA is a relation.

+

Each transition of the NDFA is a join condition + projection

+
+ +
+

Example

+ +
    +
  1. Look for high-volume (10,000 or more) trades
  2. +
  3. When one happens, check if it's followed by a 10 minute sequence of trades with dropping prices
  4. +
  5. Wait for the stock to rally (5% higher than its lowest point) and alert me
  6. +
+
+ +
+

+  SELECT Name, MaxPrice, MinPrice, Price as FinalPrice
+      -- Only consider aggregates spanning 10 minutes or more
+  FROM FILTER { dur ≥ 10 min } (
+    ( 
+      -- Trigger aggregate when a Stock w/ Volume > 10000 sells
+      SELECT Name, Price_1 AS MaxPrice, Price as MinPrice
+      FROM Filter { Volume > 10000 } Stock
+    ) FOLD { 
+        $2.Name = $.Name,   -- Grouping Condition
+        $2.Price < $.Price  -- Continue Condition
+    } Stock -- Fold over any stock
+  ) NEXT { 
+      -- Find the next upturn after a 10 minute descending run
+      $2.Name = $1.Name AND $2.Price > 1.05 * $1.MinPrice
+  } Stock
+    
+
+ +
+ +
    +
  • A: Sequences started by a 10k trade
  • +
  • B: >10 min runs
  • +
+
+ +
+

+      CREATE TABLE A(
+        Name_l STRING,    -- From LHS
+        MaxPrice DECIMAL, -- From LHS
+        MinPrice DECIMAL, -- From LHS
+        Name_r STRING,    -- From RHS
+        Price Decimal,    -- From RHS
+        Start Int,        -- From LHS
+        End Int           -- From RHS
+      )
+    
+ +

+      CREATE TABLE B(
+        Name STRING,      
+        MaxPrice DECIMAL, 
+        MinPrice DECIMAL, 
+        Price Decimal,    
+        Start Int,        
+        End Int           
+      )
+    
+
+ +
+ +
    +
  • A: Sequences started by a 10k trade
  • +
  • B: >10 min runs
  • +
+
+ +
+ + +
NamePriceValuationTime
+ + + + + + + + +
State AState BEmitted
Name_lMinPriceName_rPriceNameMinPricePrice 
+
+ +
+ + + +
NamePriceValuationTime
IBM9015,0009:10
+ + + + + + + + + + + +
State AState BEmitted
Name_lMinPriceName_rPriceNameMinPricePrice 
IBM90IBM90
+
+ +
+ + + + +
NamePriceValuationTime
IBM9015,0009:10
IBM857,0009:15
+ + + + + + + + + + + +
State AState BEmitted
Name_lMinPriceName_rPriceNameMinPricePrice 
IBM90IBM85
+
+ +
+ + + + + +
NamePriceValuationTime
IBM9015,0009:10
IBM857,0009:15
Dell4011,0009:17
+ + + + + + + + + + + + + + +
State AState BEmitted
Name_lMinPriceName_rPriceNameMinPricePrice 
IBM90IBM85
Dell40Dell40
+
+ +
+ + + + + + +
NamePriceValuationTime
IBM9015,0009:10
IBM857,0009:15
Dell4011,0009:17
IBM818,0009:21
+ + + + + + + + + + + + + + + +
State AState BEmitted
Name_lMinPriceName_rPriceNameMinPricePrice 
IBM90IBM81IBM9081
Dell40Dell40
+
+ +
+ + + + + + + +
NamePriceValuationTime
IBM9015,0009:10
IBM857,0009:15
Dell4011,0009:17
IBM818,0009:21
MSFT256,0009:23
+ + + + + + + + + + + + + + + +
State AState BEmitted
Name_lMinPriceName_rPriceNameMinPricePrice 
IBM90IBM81IBM9081
Dell40Dell40
+
+ +
+ + + + + + + + +
NamePriceValuationTime
IBM9015,0009:10
IBM857,0009:15
Dell4011,0009:17
IBM818,0009:21
MSFT256,0009:23
IBM919,0009:24
+ + + + + + + + + + + + + + + + +
State AState BEmitted
Name_lMinPriceName_rPriceNameMinPricePrice 
IBM90IBM81IBM!
Dell40Dell40
+
+
+ +
+
+

Cayuga

+
+
+
Language
+
Maximize Expressiveness w/o Compromising Performance
+
+ +
+
Compiler
+
Emit a tight, optimized program representation
+
+ +
+
Runtime
+
Necessary support for concurrent, asynchronous execution
+
+
+
+ +
+

Challenges

+
+
Asynchronous Arrival
+
Updates may arrive out of order
+
Threading
+
Make sure each thread sees a concurrent view of the state
+
Shallow Copies
+
Need to keep track of which threads are using which state
+
Relational State
+
Lots of work for each event!
+
String Comparisons
+
Expensive!
+
+
+ +
+

Asynchronous Arrival

+ +

Simple Solution: Add a delay to event processing to buffer for out-of-order arrival.

+
+ +
+

Threading

+ +

Mostly Simple Solution: Parallel processing of one event to create a new state, swap in the new state, repeat.

+
+ +
+

Shallow Copies

+ +

Not so Simple Solution: Add an epoch-based garbage collector to detect when an object falls out of scope.

+ +

(Reference counting creates points of contention on every refcount update)

+
+ +
+

Relational State

+ +

Simple Solution: Index the states to make it easier to discover which states a new event interacts with.

+
+ +
+

String Comparison

+ +

Simple Solution: Build a dictionary of strings (can be done asynchronously while the event is waiting to be processed).

+
+
\ No newline at end of file diff --git a/src/teaching/cse-662/2019fa/slide/graphics/2019-10-24-CayugaExample.svg b/src/teaching/cse-662/2019fa/slide/graphics/2019-10-24-CayugaExample.svg new file mode 100644 index 00000000..d42f22aa --- /dev/null +++ b/src/teaching/cse-662/2019fa/slide/graphics/2019-10-24-CayugaExample.svg @@ -0,0 +1,474 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + Start + A + B + + + + e.volume >10,000 + e.Name = A.Name ANDe.END - A.START ≥ 10 min + e.Name = B.Name ANDe.price > 1.05 * B.MinPrice + e.Name ≠ B.Name + e.Name ≠ A.Name + e.name = A.Name ANDe.Price < A.Price + + + diff --git a/src/teaching/cse-662/2019fa/slide/graphics/2019-10-24-CayugaUnannotated.svg b/src/teaching/cse-662/2019fa/slide/graphics/2019-10-24-CayugaUnannotated.svg new file mode 100644 index 00000000..75ecceb2 --- /dev/null +++ b/src/teaching/cse-662/2019fa/slide/graphics/2019-10-24-CayugaUnannotated.svg @@ -0,0 +1,372 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + Start + A + B + + + + diff --git a/src/teaching/cse-662/2019fa/slide/graphics/2019-10-24-CayugaUpdates.svg b/src/teaching/cse-662/2019fa/slide/graphics/2019-10-24-CayugaUpdates.svg new file mode 100644 index 00000000..e034c2d3 --- /dev/null +++ b/src/teaching/cse-662/2019fa/slide/graphics/2019-10-24-CayugaUpdates.svg @@ -0,0 +1,464 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + Start + A + B + + + + MinPrice, MaxPrice ← e.PriceName_l, Name_r ← e.Name + Name ← Name_l + No Change + No Change + No Change + Price ← e.Price + + + diff --git a/src/teaching/cse-662/2019fa/slide/graphics/2019-10-24-DFAExample.svg b/src/teaching/cse-662/2019fa/slide/graphics/2019-10-24-DFAExample.svg new file mode 100644 index 00000000..5b2601b7 --- /dev/null +++ b/src/teaching/cse-662/2019fa/slide/graphics/2019-10-24-DFAExample.svg @@ -0,0 +1,480 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + i + + + + H + not H + + + + not i + anything + i + + not i or ! + ! + + + + Start + S1 + S2 + S3 + + diff --git a/src/teaching/cse-662/2019fa/slide/graphics/2019-10-24-NDFAExample.svg b/src/teaching/cse-662/2019fa/slide/graphics/2019-10-24-NDFAExample.svg new file mode 100644 index 00000000..a641c394 --- /dev/null +++ b/src/teaching/cse-662/2019fa/slide/graphics/2019-10-24-NDFAExample.svg @@ -0,0 +1,430 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + i + + + + H + anything + + + a + + ! + + + + Start + S1 + S2 + S3 + H + + diff --git a/src/teaching/cse-662/2019fa/slide/graphics/2019-10-24-PubSub.svg b/src/teaching/cse-662/2019fa/slide/graphics/2019-10-24-PubSub.svg new file mode 100644 index 00000000..0117ad8c --- /dev/null +++ b/src/teaching/cse-662/2019fa/slide/graphics/2019-10-24-PubSub.svg @@ -0,0 +1,2979 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/src/teaching/cse-662/2019fa/slide/graphics/DB.png b/src/teaching/cse-662/2019fa/slide/graphics/DB.png new file mode 100644 index 0000000000000000000000000000000000000000..90f993ef9257ba12a3d0d32963fac8a7d1658782 GIT binary patch literal 16335 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 NB(40hOv*Uu{{lNplO+HE literal 0 HcmV?d00001