The *Big State* Monster: Taming State Size in Multi-Way Joins with FLIP-516

A presentation at Flink Forward 2025 in October 2025 in Barcelona, Spain by Gustavo de Morais

Slide 1

Slide 1

The “Big State” Monster: Taming State Size in MultiWay Joins with FLIP-516 Gustavo de Morais, Staff Software Engineer@Confluent 13-16 October 2025 Barcelona 2025

Slide 2

Slide 2

Table of Contents 1. What are multi-way joins? 2. Why are they problematic? 3. How can we address that? The MultiJoin Operator 4. Benchmark: Binary Joins vs MultiJoin 5. What types of joins are supported? 6. Optimizations and next steps

Slide 3

Slide 3

What are multi-way joins? A big challenge for stateful scalable distributed stream processing

Slide 4

Slide 4

What are multi-way joins? select * from users join orders on users.id = orders.user_id join shipments on shipments.orderid = orders.id join details on shipments.id = details.sid join … on …

Slide 5

Slide 5

Multiple chained non-temporal binary joins users Join orders shipments details Join Join Sink

Slide 6

Slide 6

Multiple chained non-temporal binary joins users Join orders shipments details Join Join Sink

Slide 7

Slide 7

Why are they problematic?

Slide 8

Slide 8

Why are they problematic? users Join Operator event reaction 1 event 1 reaction 1 user x 1 event x 1 reaction 1 user x 1 event 1 user Join Operator Join Operator

Slide 9

Slide 9

Why are they problematic? users 100000 users Join Operator 100000 users x 1000 events 10 M event reaction 1000 event 10 reaction 100000 users x 1000s event x 10s reaction Join Operator Join Operator 100 M records

Slide 10

Slide 10

Why are they problematic? users 100000 users Join Operator 100000 users x 1000 events 10 M event 100000 users x 1000s event x 10s reaction Join Operator Join Operator 100 M records 1000 event 🚨 We store all of them in state! reaction 10 reaction ~100k records ~10M records ~100M records

Slide 11

Slide 11

Why are they problematic?

Slide 12

Slide 12

Why are they problematic? ● State and checkpoints size can become huge ● Checkpoints start to timeout ● Recovery time is long due to state size ● Processing rate drops heavily ● … and the pipeline becomes unhealthy

Slide 13

Slide 13

How can we address that? FLIP-516 Multi-way Join Operator

Slide 14

Slide 14

FLIP-516: Multi-way Join Operator users orders shipments MultiJoin Operator Sink details

Slide 15

Slide 15

FLIP-516: Multi-way Join Operator users orders ✅ Only input records in state ✅ No intermediate state shipments MultiJoin Operator ✅ Faster for big jobs ✅ No shuffling 🟡 Data skew ⛔️ Reprocessing details ⛔️ Common join key required

Slide 16

Slide 16

FLIP-516: Multi-way Join Operator users 100000 user Join Operator 100000 users x 1000 events 100000 users x 1000s event x 10s reaction Join Operator Join Operator 10 M event reaction 100 M records 1000 event 10 reaction We use ~1% of the previous state ~100k records ~10M records ~100M records

Slide 17

Slide 17

Why are they problematic?

Slide 18

Slide 18

FLIP-516: Multi-way Join Operator SET ‘table.optimizer.multi-join.enabled’ = ‘true’;

Slide 19

Slide 19

Benchmark Binary Joins vs MultiJoin

Slide 20

Slide 20

Benchmark: parameters ● Tried to keep as generic as possible ● Parallelism 10 ● Records equally distributed ● 10 chained LEFT joins ● No considerable record amplification ● RocksDB as state backend ● 2.8 GB Managed Memory (used for state cache) ● Streaming mode ● Running in Apple M1 Pro 32 GB

Slide 21

Slide 21

Benchmark: Execution Time vs Input Records

Slide 22

Slide 22

Benchmark: State Size vs Input Records

Slide 23

Slide 23

What types of joins are supported?

Slide 24

Slide 24

What types of joins are supported? Supported ✅ Inner joins Future Work ❌ FULL OUTER JOINS - also requires calcite change ✅ Left joins 🚧 Right joins (wip) ❌ SEMI and ANTI joins - also requires calcite change ✅ Streaming mode ❌ Temporal Joins

Slide 25

Slide 25

Partitioning: common join key Supported Not supported ✅ A JOIN B ON A.key1 = B.key JOIN C ON A.key1 = C.key ❌ A JOIN B ON A.key1 = B.key1 JOIN C ON B.key2 = C.key2 ✅ A JOIN B ON A.key = B.key1 JOIN C ON B.key1 = C.key2 (Partition by key via transitivity) ✅ A JOIN B ON A.key = B.key1 JOIN C ON B.key1 = C.key2 AND B.key10 = C.key.10

Slide 26

Slide 26

Partitioning: common join key MultiJoin Operator Color? MultiJoin Operator MultiJoin Operator

Slide 27

Slide 27

Partitioning: common join key MultiJoin Operator Color? MultiJoin Operator ? ? ? ? MultiJoin Operator

Slide 28

Slide 28

Partitioning with multiple keys MultiJoin Operator MultiJoin Operator

Slide 29

Slide 29

Optimizations and next steps

Slide 30

Slide 30

Optimizations and next steps ● Set STATE TTL ○ Try to keep the state size < Managed Memory ● Stick to append mode ● Avoid outer joins ○ Toggle upsert mode ○ Have natural amplification ● Try to preserve upsert keys ● Optimize binary joins ○ Reorder Joins ○ Less frequently updated tables to the left -> More frequently updated tables to the right ● Use temporal joins

Slide 31

Slide 31

Optimizations and next steps ● Stabilize MultiJoinOperator for Flink 2.2 ● (Adaptive) MultiJoinOperator ○ Cache some intermediate state ○ Cache hot keys ○ Change traversal order ● BroadcastMultiJoinOperator ● DeltaMultiJoinOperator ● LookupMultiJoin ● Temporal MultiJoinOperators

Slide 32

Slide 32

More details Documentation

Slide 33

Slide 33

Thank You Gustavo de Morais, Staff Software Engineer at Confluent Barcelona 2025

Slide 34

Slide 34

Slide 35

Slide 35

Slide 36

Slide 36

Extra slides Add Title of the Upcoming Section

Slide 37

Slide 37

Operator State Layout Extra slide for questions

Slide 38

Slide 38

Operator State Layout JoinKeyContainsUniqueKey ● MapStateDescriptor<RowData, RowData> ● Stores data as MapState<JoinKey, Record> InputSideHasUniqueKey ● MapState<RowData, RowData> ● Stores data as MapState<CompositeKey<JoinKey, UniqueKey>, Record> InputSideHasNoUniqueKey ● MapStateDescriptor<RowData, Integer> ● Stores data as MapState<CompositeKey<JoinKey, Record>, Count>

Slide 39

Slide 39

FLIP-516: Multi-way Join Operator What if we have record amplification? Docs: https://nightlies.apache.org/flink/flink-docs-master/docs/dev/table/tuning/#multijoin-operator-example—-benchmark

Slide 40

Slide 40

Benchmark: Binary Joins vs MultiJoin

Slide 41

Slide 41

MultiJoin Operator Inside the operator - examples

Slide 42

Slide 42

Inside the StreamingMultiJoinOperator SELECT users.id, users.name, orders.id, payment.status FROM users JOIN orders on users.id = orders.uid JOIN payment orders.uid = payment.uid AND orders.id = payment.oid users orders [1, “Joe”] [1, “order_1”, “Phone”] payments [1, “order_1”, “paid”] output +I[1, “Joe”, “Phone”, “paid”]

Slide 43

Slide 43

The new StreamingMultiJoinOperator [1, “order_2”, “Car”] users orders [1, “Joe”] [1, “order_1”, “Phone”] ️1 payments [1, “order_1”, “paid”] output +I[1, “Joe”, “Phone”, “paid”]

Slide 44

Slide 44

The new StreamingMultiJoinOperator [1, “order_2”, “Car”] users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_2”, “Car”] payments [1, “order_1”, “paid”] output +I[1, “Joe”, “Phone”, “paid”]

Slide 45

Slide 45

The new StreamingMultiJoinOperator [1, “order_2”, “Car”] users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_2”, “Car”] payments [1, “order_1”, “paid”] output +I[1, “Joe”, “Phone”, “paid”]

Slide 46

Slide 46

The new StreamingMultiJoinOperator [1, “order_2”, “Car”] users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_2”, “Car”] payments [1, “order_1”, “paid”] output +I[1, “Joe”, “Phone”, “paid”]

Slide 47

Slide 47

The new StreamingMultiJoinOperator [1, “order_2”, “Car”] users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_2”, “Car”] payments [1, “order_1”, “paid”] output +I[1, “Joe”, “Phone”, “paid”]

Slide 48

Slide 48

The new StreamingMultiJoinOperator [1, “order_2”, “Car”] users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_2”, “Car”] output payments [1, “order_1”, “paid”] ❌ +I[1, “Joe”, “Phone”, “paid”]

Slide 49

Slide 49

The new StreamingMultiJoinOperator [1, “order_2”, “pending”] users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_2”, “Car”] payments [1, “order_1”, “paid”] output +I[1, “Joe”, “Phone”, “paid”]

Slide 50

Slide 50

The new StreamingMultiJoinOperator [1, “order_2”, “pending”] payments users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_1”, “paid”] [1, “order_2”, “Car”] [1, “order_2”, “pending”] output +I[1, “Joe”, “Phone”, “paid”]

Slide 51

Slide 51

The new StreamingMultiJoinOperator [1, “order_2”, “pending”] payments users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_1”, “paid”] [1, “order_2”, “Car”] [1, “order_2”, “pending”] output +I[1, “Joe”, “Phone”, “paid”]

Slide 52

Slide 52

The new StreamingMultiJoinOperator [1, “order_2”, “pending”] payments users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_1”, “paid”] [1, “order_2”, “Car”] [1, “order_2”, “pending”] output +I[1, “Joe”, “Phone”, “paid”]

Slide 53

Slide 53

The new StreamingMultiJoinOperator [1, “order_2”, “pending”] payments users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_1”, “paid”] [1, “order_2”, “Car”] [1, “order_2”, “pending”] output +I[1, “Joe”, “Phone”, “paid”]

Slide 54

Slide 54

The new StreamingMultiJoinOperator [1, “order_2”, “pending”] output payments users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_1”, “paid”] [1, “order_2”, “Car”] [1, “order_2”, “pending”] +I[1, “Joe”, “Phone”, “paid”] ❌

Slide 55

Slide 55

The new StreamingMultiJoinOperator [1, “order_2”, “pending”] payments users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_1”, “paid”] [1, “order_2”, “Car”] [1, “order_2”, “pending”] output +I[1, “Joe”, “Phone”, “paid”]

Slide 56

Slide 56

The new StreamingMultiJoinOperator [1, “order_2”, “pending”] payments users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_1”, “paid”] [1, “order_2”, “Car”] [1, “order_2”, “pending”] output +I[1, “Joe”, “Phone”, “paid”]

Slide 57

Slide 57

The new StreamingMultiJoinOperator [1, “order_2”, “pending”] payments users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_1”, “paid”] [1, “order_2”, “Car”] [1, “order_2”, “pending”] output +I[1, “Joe”, “Phone”, “paid”]

Slide 58

Slide 58

The new StreamingMultiJoinOperator [1, “order_2”, “pending”] output payments users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_1”, “paid”] [1, “order_2”, “Car”] [1, “order_2”, “pending”] +I[1, “Joe”, “Phone”, “paid”] ✅ +I[1, “Joe”, “Car”, “pending”]

Slide 59

Slide 59

The new StreamingMultiJoinOperator +U[1, “order_2”, “paid”] payments output users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_1”, “paid”] +I[1, “Joe”, “Phone”, “paid”] [1, “order_2”, “Car”] [1, “order_2”, “pending”] +I[1, “Joe”, “Car”, “pending”]

Slide 60

Slide 60

The new StreamingMultiJoinOperator +U[1, “order_2”, “paid”] payments output users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_1”, “paid”] +I[1, “Joe”, “Phone”, “paid”] [1, “order_2”, “Car”] [1, “order_2”, “pending”] +I[1, “Joe”, “Car”, “pending”] [1, “order_2”, “paid”]

Slide 61

Slide 61

The new StreamingMultiJoinOperator +U[1, “order_2”, “paid”] payments output users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_1”, “paid”] +I[1, “Joe”, “Phone”, “paid”] [1, “order_2”, “Car”] [1, “order_2”, “pending”] +I[1, “Joe”, “Car”, “pending”] [1, “order_2”, “paid”]

Slide 62

Slide 62

The new StreamingMultiJoinOperator +U[1, “order_2”, “paid”] payments output users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_1”, “paid”] +I[1, “Joe”, “Phone”, “paid”] [1, “order_2”, “Car”] [1, “order_2”, “pending”] +I[1, “Joe”, “Car”, “pending”] [1, “order_2”, “paid”]

Slide 63

Slide 63

The new StreamingMultiJoinOperator +U[1, “order_2”, “paid”] output payments users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_1”, “paid”] +I[1, “Joe”, “Phone”, “paid”] [1, “order_2”, “Car”] [1, “order_2”, “pending”] +I[1, “Joe”, “Car”, “pending”] [1, “order_2”, “paid”] ❌

Slide 64

Slide 64

The new StreamingMultiJoinOperator +U[1, “order_2”, “paid”] payments output users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_1”, “paid”] +I[1, “Joe”, “Phone”, “paid”] [1, “order_2”, “Car”] [1, “order_2”, “pending”] +I[1, “Joe”, “Car”, “pending”] [1, “order_2”, “paid”]

Slide 65

Slide 65

The new StreamingMultiJoinOperator +U[1, “order_2”, “paid”] payments output users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_1”, “paid”] +I[1, “Joe”, “Phone”, “paid”] [1, “order_2”, “Car”] [1, “order_2”, “pending”] +I[1, “Joe”, “Car”, “pending”] [1, “order_2”, “paid”]

Slide 66

Slide 66

The new StreamingMultiJoinOperator +U[1, “order_2”, “paid”] output payments users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_1”, “paid”] +I[1, “Joe”, “Phone”, “paid”] [1, “order_2”, “Car”] [1, “order_2”, “pending”] +I[1, “Joe”, “Car”, “pending”] [1, “order_2”, “paid”] ✅

Slide 67

Slide 67

The new StreamingMultiJoinOperator +U[1, “order_2”, “paid”] output payments users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_1”, “paid”] +I[1, “Joe”, “Phone”, “paid”] [1, “order_2”, “Car”] [1, “order_2”, “pending”] +I[1, “Joe”, “Car”, “pending”] [1, “order_2”, “paid”] ✅ +U[1, “Joe”, “Car”, “paid”]

Slide 68

Slide 68

The new StreamingMultiJoinOperator +U[1, “order_2”, “paid”] output payments users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_1”, “paid”] +I[1, “Joe”, “Phone”, “paid”] [1, “order_2”, “Car”] [1, “order_2”, “pending”] +I[1, “Joe”, “Car”, “pending”] [1, “order_2”, “paid”] ✅ +U[1, “Joe”, “Car”, “paid”]

Slide 69

Slide 69

The new StreamingMultiJoinOperator +U[1, “order_2”, “paid”] payments output users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_1”, “paid”] +I[1, “Joe”, “Phone”, “paid”] [1, “order_2”, “Car”] [1, “order_2”, “paid”] +I[1, “Joe”, “Car”, “pending”] +U[1, “Joe”, “Car”, “paid”]

Slide 70

Slide 70

Inside The new theStreamingMultiJoinOperator StreamingMultiJoinOperator - Left join SELECT users.id, users.name, orders.id, payment.status FROM users LEFT JOIN orders on users.id = orders.uid LEFT JOIN payment orders.uid = payment.uid AND orders.id = payment.oid users orders payments output

Slide 71

Slide 71

The new StreamingMultiJoinOperator - Left join +I[1, “Joe”] users orders ️1 payments output

Slide 72

Slide 72

The new StreamingMultiJoinOperator - Left join +I[1, “Joe”] users +I [1, “Joe”] orders payments output +I[1, “Joe”, “Phone”, “paid”]

Slide 73

Slide 73

The new StreamingMultiJoinOperator - Left join [1, “Joe”] orders users +I [1, “Joe”] 🔗0 payments output

Slide 74

Slide 74

The new StreamingMultiJoinOperator - Left join [1, “Joe”] orders users +I [1, “Joe”] 🔗0 [null, null, null] payments output

Slide 75

Slide 75

The new StreamingMultiJoinOperator - Left join [1, “Joe”] orders users +I [1, “Joe”] 🔗0 [null, null, null] payments output

Slide 76

Slide 76

The new StreamingMultiJoinOperator - Left join [1, “Joe”] +I [1, “Joe”] payments orders users 🔗0 [null, null, null] 🔗0 output

Slide 77

Slide 77

The new StreamingMultiJoinOperator - Left join [1, “Joe”] +I [1, “Joe”] payments orders users 🔗0 [null, null, null] 🔗0 [null, null, null] output

Slide 78

Slide 78

The new StreamingMultiJoinOperator - Left join [1, “Joe”] +I [1, “Joe”] payments orders users 🔗0 [null, null, null] 🔗0 [null, null, null] output +I[1, “Joe”, null, null]

Slide 79

Slide 79

The new StreamingMultiJoinOperator - Left join [1, “Joe”] +I [1, “Joe”] payments orders users 🔗0 [null, null, null] 🔗0 [null, null, null] output +I[1, “Joe”, null, null]

Slide 80

Slide 80

The new StreamingMultiJoinOperator - Left join [1, “Joe”] orders users +I [1, “Joe”] 🔗0 [null, null, null] payments output +I[1, “Joe”, null, null]

Slide 81

Slide 81

The new StreamingMultiJoinOperator - Left join [1, “Joe”] users +I [1, “Joe”] orders payments output +I[1, “Joe”, null, null]

Slide 82

Slide 82

The new StreamingMultiJoinOperator - Left join Waiting for records users +I [1, “Joe”] orders payments output +I[1, “Joe”, null, null]

Slide 83

Slide 83

The new StreamingMultiJoinOperator - Left join +I[1, “order_1”, “Phone”] users +I [1, “Joe”] orders payments output +I[1, “Joe”, null, null]

Slide 84

Slide 84

The new StreamingMultiJoinOperator - Left join [1, “order_1”, “Phone”] +I users orders [1, “Joe”] [1, “order_1”, “Phone”] payments output +I[1, “Joe”, null, null]

Slide 85

Slide 85

The new StreamingMultiJoinOperator - Left join [1, “order_1”, “Phone”] +I users orders [1, “Joe”] [1, “order_1”, “Phone”] payments output +I[1, “Joe”, null, null]

Slide 86

Slide 86

The new StreamingMultiJoinOperator - Left join [1, “order_1”, “Phone”] orders users +I [1, “Joe”] 🔗0 [1, “order_1”, “Phone”] payments output +I[1, “Joe”, null, null]

Slide 87

Slide 87

The new StreamingMultiJoinOperator - Left join [1, “order_1”, “Phone”] +I [1, “Joe”] payments orders users 🔗1 [1, “order_1”, “Phone”] ✅ output +I[1, “Joe”, null, null] Important transition

Slide 88

Slide 88

The new StreamingMultiJoinOperator - Left join [1, “order_1”, “Phone”] orders users -D [1, “Joe”] 🔗1 [null, null, null] payments output +I[1, “Joe”, null, null]

Slide 89

Slide 89

The new StreamingMultiJoinOperator - Left join [1, “order_1”, “Phone”] -D [1, “Joe”] payments orders users 🔗1 [null, null, null] 🔗0 [null, null, null] output +I[1, “Joe”, null, null]

Slide 90

Slide 90

The new StreamingMultiJoinOperator - Left join [1, “order_1”, “Phone”] -D [1, “Joe”] payments orders users 🔗1 [null, null, null] 🔗0 [null, null, null] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null]

Slide 91

Slide 91

The new StreamingMultiJoinOperator - Left join [1, “order_1”, “Phone”] -D [1, “Joe”] payments orders users 🔗1 [null, null, null] 🔗0 [null, null, null] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null]

Slide 92

Slide 92

The new StreamingMultiJoinOperator - Left join [1, “order_1”, “Phone”] orders users -D [1, “Joe”] 🔗1 [null, null, null] payments output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null]

Slide 93

Slide 93

The new StreamingMultiJoinOperator - Left join [1, “order_1”, “Phone”] orders users +I [1, “Joe”] 🔗1 [1, “order_1”, “Phone”] payments output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null]

Slide 94

Slide 94

The new StreamingMultiJoinOperator - Left join [1, “order_1”, “Phone”] +I [1, “Joe”] payments orders users 🔗1 [1, “order_1”, “Phone”] 🔗0 [null, null, null] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null]

Slide 95

Slide 95

The new StreamingMultiJoinOperator - Left join [1, “order_1”, “Phone”] +I [1, “Joe”] payments orders users 🔗1 [1, “order_1”, “Phone”] 🔗0 [null, null, null] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null]

Slide 96

Slide 96

The new StreamingMultiJoinOperator - Left join +I[1, “order_1”, “paid”] orders users +I [1, “Joe”] 🔗1 [1, “order_1”, “Phone”] payments output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null]

Slide 97

Slide 97

The new StreamingMultiJoinOperator - Left join [1, “order_1”, “paid”] +I [1, “Joe”] 🔗1 [1, “order_1”, “Phone”] output payments orders users 🔗1 [1, “order_1”, “paid”] ✅ +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null]

Slide 98

Slide 98

The new StreamingMultiJoinOperator - Left join [1, “order_1”, “paid”] -D [1, “Joe”] payments orders users 🔗1 [1, “order_1”, “Phone”] 🔗1 [null, null, null] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null]

Slide 99

Slide 99

The new StreamingMultiJoinOperator - Left join [1, “order_1”, “paid”] +I [1, “Joe”] payments orders users 🔗1 [1, “order_1”, “Phone”] 🔗1 [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] +I[1, “Joe”, order_1, paid]

Slide 100

Slide 100

The new StreamingMultiJoinOperator - Left join -D[1, “order_1”, “Phone”] +I[1, “order_1”, “Phone 1”] users orders [1, “Joe”] [1, “order_1”, “Phone”] payments [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] +I[1, “Joe”, order_1, paid]

Slide 101

Slide 101

The new StreamingMultiJoinOperator - Left join -D[1, “order_1”, “Phone”] users orders [1, “Joe”] [1, “order_1”, “Phone”] payments [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1,

Slide 102

Slide 102

The new StreamingMultiJoinOperator - Left join -D[1, “order_1”, “Phone”] users orders [1, “Joe”] [1, “order_1”, “Phone”] [1, “order_1”, “Phone”] payments [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1,

Slide 103

Slide 103

The new StreamingMultiJoinOperator - Left join -D[1, “order_1”, “Phone”] orders users [1, “Joe”] 🔗0 [1, “order_1”, “Phone”] [1, “order_1”, “Phone”] payments [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1,

Slide 104

Slide 104

The new StreamingMultiJoinOperator - Left join -D[1, “order_1”, “Phone”] [1, “Joe”] payments orders users 🔗1 [1, “order_1”, “Phone”] ✅ [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] [1, “order_1”, “Phone”] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, This is a essential reprocessing

Slide 105

Slide 105

The new StreamingMultiJoinOperator - Left join -D[1, “order_1”, “Phone”] -D [1, “Joe”] payments orders users 🔗1 [1, “order_1”, “Phone”] [1, “order_1”, “Phone”] [1, order_1, paid] ✅ output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1,

Slide 106

Slide 106

West Eleven Restaurant The new StreamingMultiJoinOperator - Left join -D[1, “order_1”, “Phone”] -D [1, “Joe”] payments orders users 🔗0 [1, “order_1”, “Phone”] [1, “order_1”, “Phone”] [1, order_1, paid] ✅ output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1,

Slide 107

Slide 107

The new StreamingMultiJoinOperator - Left join -D[1, “order_1”, “Phone”] orders users -D [1, “Joe”] 🔗0 [1, “order_1”, “Phone”] [1, “order_1”, “Phone”] payments [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1,

Slide 108

Slide 108

The new StreamingMultiJoinOperator - Left join -D[1, “order_1”, “Phone”] orders users -D [1, “Joe”] 🔗0 [1, “order_1”, “Phone”] [1, “order_1”, “Phone”] output payments [1, order_1, paid] ✅ +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1,

Slide 109

Slide 109

The new StreamingMultiJoinOperator - Left join -D[1, “order_1”, “Phone”] orders users -D [1, “Joe”] 🔗0 [1, “order_1”, “Phone”] [1, “order_1”, “Phone”] output payments [1, order_1, paid] ✅ +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid]

Slide 110

Slide 110

The new StreamingMultiJoinOperator - Left join -D[1, “order_1”, “Phone”] orders users -D [1, “Joe”] 🔗0 [1, “order_1”, “Phone”] [1, “order_1”, “Phone”] output payments [1, order_1, paid] ✅ +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid]

Slide 111

Slide 111

The new StreamingMultiJoinOperator - Left join -D[1, “order_1”, “Phone”] orders users -D [1, “Joe”] 🔗0 [1, “order_1”, “Phone”] [1, “order_1”, “Phone”] payments [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid]

Slide 112

Slide 112

The new StreamingMultiJoinOperator - Left join -D[1, “order_1”, “Phone”] orders users +I [1, “Joe”] 🔗0 [1, “order_1”, “Phone”] [null, null, null] payments [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid]

Slide 113

Slide 113

The new StreamingMultiJoinOperator - Left join -D[1, “order_1”, “Phone”] +I [1, “Joe”] payments orders users 🔗0 [1, “order_1”, “Phone”] [null, null, null] 🔗0 [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid]

Slide 114

Slide 114

The new StreamingMultiJoinOperator - Left join -D[1, “order_1”, “Phone”] +I [1, “Joe”] 🔗0 [1, “order_1”, “Phone”] [null, null, null] output payments orders users 🔗0 [1, order_1, paid] ❌ +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid]

Slide 115

Slide 115

The new StreamingMultiJoinOperator - Left join -D[1, “order_1”, “Phone”] +I [1, “Joe”] payments orders users 🔗0 [1, “order_1”, “Phone”] [1, order_1, paid] +I[1, “Joe”, null, null] [null, null, null] -D[1, “Joe”, null, null] 🔗0 [null, null, null] output +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid]

Slide 116

Slide 116

The new StreamingMultiJoinOperator - Left join -D[1, “order_1”, “Phone”] +I [1, “Joe”] payments orders users 🔗0 [1, “order_1”, “Phone”] [1, order_1, paid] +I[1, “Joe”, null, null] [null, null, null] -D[1, “Joe”, null, null] 🔗0 [null, null, null] output +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null]

Slide 117

Slide 117

The new StreamingMultiJoinOperator - Left join -D[1, “order_1”, “Phone”] +I [1, “Joe”] payments orders users 🔗0 [1, “order_1”, “Phone”] [1, order_1, paid] +I[1, “Joe”, null, null] [null, null, null] -D[1, “Joe”, null, null] 🔗0 [null, null, null] output +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null]

Slide 118

Slide 118

The new StreamingMultiJoinOperator - Left join -D[1, “order_1”, “Phone”] orders users -D [1, “Joe”] 🔗0 [1, “order_1”, “Phone”] [null, null, null] payments [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null]

Slide 119

Slide 119

The new StreamingMultiJoinOperator - Left join -D[1, “order_1”, “Phone”] -D users orders [1, “Joe”] [1, “order_1”, “Phone”] payments [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null]

Slide 120

Slide 120

The new StreamingMultiJoinOperator - Left join -D[1, “order_1”, “Phone”] users -D [1, “Joe”] orders payments [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null] Updated state

Slide 121

Slide 121

The new StreamingMultiJoinOperator - Left join +I[1, “order_1”, “Phone 1”] users [1, “Joe”] orders payments [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null]

Slide 122

Slide 122

The new StreamingMultiJoinOperator - Left join +I[1, “order_1”, “Phone 1”] users orders [1, “Joe”] [1, “order_1”, “Phone 1”] payments [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null]

Slide 123

Slide 123

The new StreamingMultiJoinOperator - Left join +I[1, “order_1”, “Phone 1”] users orders [1, “Joe”] [1, “order_1”, “Phone 1”] payments [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null]

Slide 124

Slide 124

The new StreamingMultiJoinOperator - Left join +I[1, “order_1”, “Phone 1”] orders users +I [1, “Joe”] 🔗0 [1, “order_1”, “Phone 1”] payments [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null]

Slide 125

Slide 125

The new StreamingMultiJoinOperator - Left join +I[1, “order_1”, “Phone 1”] +I [1, “Joe”] payments orders users 🔗1 [1, “order_1”, “Phone 1”] ✅ [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null]

Slide 126

Slide 126

The new StreamingMultiJoinOperator - Left join +I[1, “order_1”, “Phone 1”] orders users -D [1, “Joe”] 🔗1 [null, null, null] payments [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null]

Slide 127

Slide 127

The new StreamingMultiJoinOperator - Left join +I[1, “order_1”, “Phone 1”] -D [1, “Joe”] payments orders users 🔗1 [null, null, null] 🔗0 [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null]

Slide 128

Slide 128

The new StreamingMultiJoinOperator - Left join +I[1, “order_1”, “Phone 1”] -D [1, “Joe”] 🔗1 [null, null, null] output payments orders users 🔗0 [1, order_1, paid] ❌ +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null]

Slide 129

Slide 129

The new StreamingMultiJoinOperator - Left join +I[1, “order_1”, “Phone 1”] -D [1, “Joe”] payments orders users 🔗1 [null, null, null] output [1, order_1, paid] +I[1, “Joe”, null, null] [null, null, null] -D[1, “Joe”, null, null] 🔗0 +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null]

Slide 130

Slide 130

The new StreamingMultiJoinOperator - Left join +I[1, “order_1”, “Phone 1”] -D [1, “Joe”] payments orders users 🔗1 [null, null, null] output [1, order_1, paid] +I[1, “Joe”, null, null] [null, null, null] -D[1, “Joe”, null, null] 🔗0 +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null] -D[1, “Joe”, null, null]

Slide 131

Slide 131

The new StreamingMultiJoinOperator - Left join +I[1, “order_1”, “Phone 1”] -D [1, “Joe”] payments orders users 🔗1 [null, null, null] output [1, order_1, paid] +I[1, “Joe”, null, null] [null, null, null] -D[1, “Joe”, null, null] 🔗0 +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null] -D[1, “Joe”, null, null]

Slide 132

Slide 132

The new StreamingMultiJoinOperator - Left join +I[1, “order_1”, “Phone 1”] orders users -D [1, “Joe”] 🔗1 [null, null, null] payments [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null] -D[1, “Joe”, null, null]

Slide 133

Slide 133

The new StreamingMultiJoinOperator - Left join +I[1, “order_1”, “Phone 1”] orders users +I [1, “Joe”] 🔗1 [1, “order_1”, “Phone 1”] payments [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null] -D[1, “Joe”, null, null]

Slide 134

Slide 134

The new StreamingMultiJoinOperator - Left join +I[1, “order_1”, “Phone 1”] +I [1, “Joe”] payments orders users 🔗1 [1, “order_1”, “Phone 1”] 🔗0 [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null] -D[1, “Joe”, null, null]

Slide 135

Slide 135

The new StreamingMultiJoinOperator - Left join +I[1, “order_1”, “Phone 1”] +I [1, “Joe”] payments orders users 🔗1 [1, “order_1”, “Phone 1”] 🔗1 [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null] -D[1, “Joe”, null, null]

Slide 136

Slide 136

The new StreamingMultiJoinOperator - Left join +I[1, “order_1”, “Phone 1”] +I [1, “Joe”] payments orders users 🔗1 [1, “order_1”, “Phone 1”] 🔗1 [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, paid] order.name field is now Phone

Slide 137

Slide 137

The new StreamingMultiJoinOperator - Left join +I[1, “order_1”, “Phone 1”] +I [1, “Joe”] payments orders users 🔗1 [1, “order_1”, “Phone 1”] 🔗1 [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, paid]

Slide 138

Slide 138

The new StreamingMultiJoinOperator - Left join +I[1, “order_1”, “Phone 1”] orders users +I [1, “Joe”] 🔗1 [1, “order_1”, “Phone 1”] payments [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, paid]

Slide 139

Slide 139

The new StreamingMultiJoinOperator - Left join +I[1, “order_1”, “Phone 1”] orders users +I [1, “Joe”] 🔗1 [1, “order_1”, “Phone 1”] payments [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, paid]

Slide 140

Slide 140

The new StreamingMultiJoinOperator - Left join Waiting on new events users orders [1, “Joe”] [1, “order_1”, “Phone 1”] payments [1, order_1, paid] output +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, null] -D[1, “Joe”, order_1, null] -I[1, “Joe”, order_1, paid] +I[1, -D[1, “Joe”, order_1, paid] +I[1, “Joe”, null, null] -D[1, “Joe”, null, null] +I[1, “Joe”, order_1, paid]

Slide 141

Slide 141

Wave PatternsFeel free to integrate into your presentation

Slide 142

Slide 142

2009 2009 2009 2009 2009 2009