You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Eppo's warehouse native approach makes integration easy, transparent, and secure but it also creates a dependency on the underlying warehouse database structure. Knowing how to configure your tables to work with Eppo properly is important to minimizing run-times and compute used.
8
+
Eppo's warehouse native approach makes integration easy, transparent, and secure but it also creates a dependency on the underlying warehouse database structure. Knowing how to configure your tables to work with Eppo properly is important to minimizing runtimes and compute used.
9
9
10
-
This page outlines some best practices to help keep Eppo's pipeline as lightweight as possible.
10
+
This page outlines some best practices to help keep Eppo's data pipeline as lightweight as possible.
11
11
12
-
## Data modeling
12
+
## Materialize data upstream of Eppo
13
13
14
-
Eppo's SQL editor makes it easy to quickly pilot new SQL logic, but in the steady state all complex logic (joins, aggregations, etc.) should happen upstream of Eppo in your data warehouse's transformation layer. In Eppo, the SQL should then be a simple `SELECT ... FROM` statement (just make sure the table is materialized as table and not a view).
14
+
Eppo's SQL editor makes it easy to quickly pilot new SQL logic, but in the steady state all complex logic (joins, aggregations, etc.) should happen upstream of Eppo in your data warehouse's transformation layer. In Eppo, the SQL should then be a simple `SELECT ... FROM` statement (just make sure the table is materialized as a table and not a view).
15
15
16
16
By materializing data upstream of Eppo, you can avoid having Eppo perform complex joins and aggregations separately for each experiment. Simple `WHERE` statements are typically fine to include in Eppo, just avoid `JOIN` and `GROUP BY`.
17
17
18
-
### One metric table vs many
18
+
##Pre-aggregating high volume data sources
19
19
20
-
The most intensive part of the experiment pipeline is often joining assignments to facts (metric events). By consolidating multiple metric events into one pre-computed table, you can reduce the number of times that Eppo has to perform this join.
20
+
If your metric sources are extremely large you might want to consider aggregating up to the subject-day grain (e.g., daily user values) before adding to Eppo. For example, imagine you have a large table of user events. This table might look something like this:
21
+
22
+
| user_id | event_type | timestamp |
23
+
|---------|------------|------------|
24
+
| 123 | login | 2024-01-01 00:01:00|
25
+
| 123 | search | 2024-01-01 00:01:15 |
26
+
| 124 | login | 2024-01-03 00:02:00 |
27
+
| 124 | search | 2024-01-04 00:02:20 |
28
+
| 124 | search | 2024-01-04 00:02:40 |
29
+
| 125 | support_ticket | 2024-01-05 00:03:05 |
30
+
31
+
Instead of pointing Eppo at this table directly, consider creating a pre-aggregated table:
If you're using a data transformation tool such as dbt, you can create a table like this with the following SQL:
21
42
22
43
```sql
23
-
SELECT
24
-
...
25
-
FROM assignments AS a
26
-
LEFT JOIN facts AS f
27
-
ONf.subject_id=a.subject_id
28
-
ANDf.timestamp>=a.timestamp
29
-
...
44
+
select
45
+
user_id,
46
+
event_type,
47
+
date(timestamp) asdate,
48
+
count(*) as event_count
49
+
from user_events
50
+
group by1, 2, 3
30
51
```
31
52
32
-
### Pre-aggregating data
53
+
You can now use this aggregated table as a fact source in Eppo and build metrics off of it just like any other fact source.
54
+
55
+
:::note
56
+
If you opt to pre-aggregate data, make sure you truncate the assignment date to the start of the day to avoid losing data from the day of assignment. Remember that Eppo only includes events that occur after the subject's first assignment into the experiment.
57
+
58
+
Pre-aggregating by date can reduce warehouse usage at the cost of some minor dilution to metrics. Specifically, all events that happen on the day of assignment will be included in the analysis, not just those after the subject is exposed to the experiment. For many use cases, this is a suitable tradeoff to make in order to drastically reduce warehouse costs.
59
+
:::
60
+
61
+
### Accounting for multiple entities
62
+
63
+
The approach above works well when you have a single entity (e.g., user). However, if you have multiple entities (e.g., user and visitor) you'll need to account for this in your pre-aggregated table. This can be done by simply adding a column for each entity. For example, consider a table of events tracked by `user_id` and `visitor_id`:
You can take the exact same approach as above but instead of only grouping by `user_id`, also group by `visitor_id`:
75
+
76
+
```sql
77
+
select
78
+
user_id,
79
+
visitor_id,
80
+
event_type,
81
+
date(timestamp) asdate,
82
+
count(*) as event_count
83
+
from user_events
84
+
group by1, 2, 3, 4
85
+
```
33
86
34
-
If your metric sources are extremely large you might want to consider aggregating up to the subject-day grain (e.g., daily user values) before adding to Eppo. If you do opt to do this, make sure you truncate the assignment date to the start of the day as well so that the join above does not remove data from the day of assignment.
87
+
Note that this is not the logic you'll enter into Eppo, but rather the logic you'll use in your data warehouse's transformation layer.
88
+
89
+
### Moving beyond just event counts
90
+
91
+
So far this all works well if you only care about the count of events or unique subjects with a specific event. Often times however, you'll want to leverage additional event metadata such as time spent on page, minutes of a video watched, etc. In this case, your pre-aggregation will need to include some more complex logic. It's often helpful to pre-aggregate data in a set of tables each specific to a given surface area or set of events.
92
+
93
+
As an example, imagine you have a simple login page and want to track whether a login was successful. You might have data that looks like this:
Simply aggregating this data by user and event type will not give you the information you need. Instead, you'll want to also leverage the event metadata. The resulting aggregated table might look like this:
105
+
106
+
| visitor_id | date | login_attempts | login_successes |
In your transformation layer, you'll need to extract the `success` field from the event metadata and then aggregate the data. This might look something like this:
114
+
115
+
```sql
116
+
select
117
+
visitor_id,
118
+
date(timestamp) asdate,
119
+
count(*) as login_attempts,
120
+
sum(
121
+
case
122
+
when parse_json(event_metadata):success ='true' then 1
123
+
else 0
124
+
end) as login_successes
125
+
from user_events
126
+
where event_type ='login'
127
+
group by1, 2
128
+
```
129
+
130
+
:::note
131
+
For events with a lot of properties (dimensions), you have two options: fan out each property value into a separate column, or include that property as an additional part of the group by statement. Properties like device type that are present for all events are typically better suited as an additional group by clause, whereas event-specific properties like "log in successful" are better to fan out into separate columns.
132
+
133
+
Depending on your use case, you may want to create one large table with all of your event types or you may want to group related events in separate tables.
134
+
:::
35
135
36
-
Pre-aggregating to the date level can reduce warehouse usage at the cost of minor dilution to metrics. Specifically, all events that happen on the day of assignment will be included, not just those after the subject is exposed to the experiment. Depending on your business and use cases, this may be a suitable tradeoff to make in order to drastically reduce warehouse costs.
136
+
By applying transformations on large data source like click stream tables, you can drastically reduce the amount of warehouse resources needed to run Eppo's data pipeline.
0 commit comments