Files
cfw-autumn/server/tinybird/scripts/benchmark_groupable.sh
amianthus 6d52409d6c feat: add Tinybird dual-write infrastructure
Add parallel event ingestion to Tinybird alongside existing Postgres/ClickHouse flow.
Events are sent to both systems simultaneously via EventBatchingManager.

- Add Tinybird client setup and ingest endpoint (zod-bird)
- Add event mapping and send utilities with retry/error handling
- Add complete Tinybird datafiles (datasources, pipes, materializations, copies, scripts)
- Modify EventBatchingManager to dual-write to SQS + Tinybird
- Route track events through batching manager

Tinybird will silently skip if not configured (TINYBIRD_URL/TINYBIRD_TOKEN).
2026-01-29 17:52:35 +00:00

311 lines
10 KiB
Bash

#!/bin/bash
# Benchmark: Global Top 9 vs Per-Bin Top 9 grouping approaches
# Tests with both low cardinality (billing_source) and high cardinality (session_id)
set -e
cd "$(dirname "$0")/.."
ORG_ID="0pCIbS4AMAFDB1iBMNhARWZt2gDtVwQx"
ENV="live"
START_DATE="2024-01-01 00:00:00"
END_DATE="2025-12-31 23:59:59"
RUNS=10
echo "=== Benchmark: Global Top 9 vs Per-Bin Top 9 ==="
echo "Org: $ORG_ID"
echo "Runs: $RUNS"
echo ""
run_benchmark() {
local name="$1"
local query_file="$2"
local times=()
echo "--- $name ---"
for i in $(seq 1 $RUNS); do
result=$(tb --cloud sql --stats "$(cat $query_file)" 2>&1)
elapsed=$(echo "$result" | grep "Query took" | awk '{print $4}')
if [ -z "$elapsed" ]; then
echo " Run $i: ERROR"
echo "$result" | head -5
continue
fi
times+=("$elapsed")
printf " Run %2d: %ss\n" "$i" "$elapsed"
done
if [ ${#times[@]} -eq 0 ]; then
echo " All runs failed!"
echo "0" > "/tmp/benchmark_${name}.txt"
return
fi
avg=$(printf '%s\n' "${times[@]}" | awk '{sum+=$1} END {printf "%.6f", sum/NR}')
min=$(printf '%s\n' "${times[@]}" | sort -n | head -1)
max=$(printf '%s\n' "${times[@]}" | sort -n | tail -1)
avg_ms=$(awk "BEGIN {printf \"%.1f\", $avg * 1000}")
echo ""
echo " Avg: ${avg}s (${avg_ms}ms) | Min: ${min}s | Max: ${max}s"
echo ""
echo "$avg" > "/tmp/benchmark_${name}.txt"
}
# Warmup
echo "Warming up..."
tb --cloud sql "SELECT 1" > /dev/null 2>&1
echo ""
# Create temp SQL files
mkdir -p /tmp/benchmark_sql
# Global Top 9 - billing_source
cat > /tmp/benchmark_sql/global_billing.sql << 'EOSQL'
WITH top_groups AS (
SELECT groupArray(9)(group_value) as top_groups
FROM (
SELECT
properties.billing_source::String as group_value,
sum(total_value) as total
FROM events_hourly_mv
WHERE
org_id = '0pCIbS4AMAFDB1iBMNhARWZt2gDtVwQx'
AND env = 'live'
AND event_name = 'usd_api_credits'
AND hour >= toDateTime('2024-01-01 00:00:00')
AND hour <= toDateTime('2025-12-31 23:59:59')
GROUP BY group_value
ORDER BY total DESC
)
),
max_per_bin AS (
SELECT max(bin_unique_count) > 9 as any_bin_truncated
FROM (
SELECT
formatDateTime(toStartOfDay(hour, 'UTC'), '%F %T') as period,
count(DISTINCT properties.billing_source::String) as bin_unique_count
FROM events_hourly_mv
WHERE
org_id = '0pCIbS4AMAFDB1iBMNhARWZt2gDtVwQx'
AND env = 'live'
AND event_name = 'usd_api_credits'
AND hour >= toDateTime('2024-01-01 00:00:00')
AND hour <= toDateTime('2025-12-31 23:59:59')
GROUP BY period
)
)
SELECT
formatDateTime(toStartOfDay(hour, 'UTC'), '%F %T') as period,
event_name,
if(
has((SELECT top_groups FROM top_groups), properties.billing_source::String),
properties.billing_source::String,
'Other'
) as group_value,
sum(total_value) as total_value,
(SELECT any_bin_truncated FROM max_per_bin) as _truncated
FROM events_hourly_mv
WHERE
org_id = '0pCIbS4AMAFDB1iBMNhARWZt2gDtVwQx'
AND env = 'live'
AND event_name = 'usd_api_credits'
AND hour >= toDateTime('2024-01-01 00:00:00')
AND hour <= toDateTime('2025-12-31 23:59:59')
GROUP BY period, event_name, group_value
ORDER BY period, event_name, group_value
EOSQL
# Per-Bin Top 9 - billing_source
cat > /tmp/benchmark_sql/perbin_billing.sql << 'EOSQL'
WITH base AS (
SELECT
formatDateTime(toStartOfDay(hour, 'UTC'), '%F %T') as period,
event_name,
properties.billing_source::String as group_value,
sum(total_value) as total_value
FROM events_hourly_mv
WHERE
org_id = '0pCIbS4AMAFDB1iBMNhARWZt2gDtVwQx'
AND env = 'live'
AND event_name = 'usd_api_credits'
AND hour >= toDateTime('2024-01-01 00:00:00')
AND hour <= toDateTime('2025-12-31 23:59:59')
GROUP BY period, event_name, group_value
),
ranked AS (
SELECT
*,
row_number() OVER (PARTITION BY period, event_name ORDER BY total_value DESC) as rn
FROM base
)
SELECT
period,
event_name,
if(rn <= 9, group_value, 'Other') as group_value,
sum(total_value) as total_value,
max(rn) > 9 as _truncated
FROM ranked
GROUP BY period, event_name, group_value
ORDER BY period, event_name, group_value
EOSQL
# Global Top 9 - session_id
cat > /tmp/benchmark_sql/global_session.sql << 'EOSQL'
WITH top_groups AS (
SELECT groupArray(9)(group_value) as top_groups
FROM (
SELECT
properties.session_id::String as group_value,
sum(total_value) as total
FROM events_hourly_mv
WHERE
org_id = '0pCIbS4AMAFDB1iBMNhARWZt2gDtVwQx'
AND env = 'live'
AND event_name = 'usd_api_credits'
AND hour >= toDateTime('2024-01-01 00:00:00')
AND hour <= toDateTime('2025-12-31 23:59:59')
GROUP BY group_value
ORDER BY total DESC
)
),
max_per_bin AS (
SELECT max(bin_unique_count) > 9 as any_bin_truncated
FROM (
SELECT
formatDateTime(toStartOfDay(hour, 'UTC'), '%F %T') as period,
count(DISTINCT properties.session_id::String) as bin_unique_count
FROM events_hourly_mv
WHERE
org_id = '0pCIbS4AMAFDB1iBMNhARWZt2gDtVwQx'
AND env = 'live'
AND event_name = 'usd_api_credits'
AND hour >= toDateTime('2024-01-01 00:00:00')
AND hour <= toDateTime('2025-12-31 23:59:59')
GROUP BY period
)
)
SELECT
formatDateTime(toStartOfDay(hour, 'UTC'), '%F %T') as period,
event_name,
if(
has((SELECT top_groups FROM top_groups), properties.session_id::String),
properties.session_id::String,
'Other'
) as group_value,
sum(total_value) as total_value,
(SELECT any_bin_truncated FROM max_per_bin) as _truncated
FROM events_hourly_mv
WHERE
org_id = '0pCIbS4AMAFDB1iBMNhARWZt2gDtVwQx'
AND env = 'live'
AND event_name = 'usd_api_credits'
AND hour >= toDateTime('2024-01-01 00:00:00')
AND hour <= toDateTime('2025-12-31 23:59:59')
GROUP BY period, event_name, group_value
ORDER BY period, event_name, group_value
EOSQL
# Per-Bin Top 9 - session_id
cat > /tmp/benchmark_sql/perbin_session.sql << 'EOSQL'
WITH base AS (
SELECT
formatDateTime(toStartOfDay(hour, 'UTC'), '%F %T') as period,
event_name,
properties.session_id::String as group_value,
sum(total_value) as total_value
FROM events_hourly_mv
WHERE
org_id = '0pCIbS4AMAFDB1iBMNhARWZt2gDtVwQx'
AND env = 'live'
AND event_name = 'usd_api_credits'
AND hour >= toDateTime('2024-01-01 00:00:00')
AND hour <= toDateTime('2025-12-31 23:59:59')
GROUP BY period, event_name, group_value
),
ranked AS (
SELECT
*,
row_number() OVER (PARTITION BY period, event_name ORDER BY total_value DESC) as rn
FROM base
)
SELECT
period,
event_name,
if(rn <= 9, group_value, 'Other') as group_value,
sum(total_value) as total_value,
max(rn) > 9 as _truncated
FROM ranked
GROUP BY period, event_name, group_value
ORDER BY period, event_name, group_value
EOSQL
echo "==========================================="
echo "=== LOW CARDINALITY: billing_source ==="
echo "==========================================="
echo ""
run_benchmark "global_billing" /tmp/benchmark_sql/global_billing.sql
run_benchmark "perbin_billing" /tmp/benchmark_sql/perbin_billing.sql
echo "==========================================="
echo "=== HIGH CARDINALITY: session_id ==="
echo "==========================================="
echo ""
run_benchmark "global_session" /tmp/benchmark_sql/global_session.sql
run_benchmark "perbin_session" /tmp/benchmark_sql/perbin_session.sql
echo "==========================================="
echo "=== SUMMARY ==="
echo "==========================================="
echo ""
# Read results
t_global_billing=$(cat /tmp/benchmark_global_billing.txt 2>/dev/null || echo "0")
t_perbin_billing=$(cat /tmp/benchmark_perbin_billing.txt 2>/dev/null || echo "0")
t_global_session=$(cat /tmp/benchmark_global_session.txt 2>/dev/null || echo "0")
t_perbin_session=$(cat /tmp/benchmark_perbin_session.txt 2>/dev/null || echo "0")
ms_global_billing=$(awk "BEGIN {printf \"%.1f\", $t_global_billing * 1000}")
ms_perbin_billing=$(awk "BEGIN {printf \"%.1f\", $t_perbin_billing * 1000}")
ms_global_session=$(awk "BEGIN {printf \"%.1f\", $t_global_session * 1000}")
ms_perbin_session=$(awk "BEGIN {printf \"%.1f\", $t_perbin_session * 1000}")
echo "LOW CARDINALITY (billing_source):"
echo " Global Top 9: ${ms_global_billing}ms"
echo " Per-Bin Top 9: ${ms_perbin_billing}ms"
if awk "BEGIN {exit !($t_global_billing > 0 && $t_perbin_billing > 0)}"; then
ratio_billing=$(awk "BEGIN {printf \"%.2f\", $t_global_billing / $t_perbin_billing}")
pct_faster=$(awk "BEGIN {printf \"%.0f\", ($t_global_billing - $t_perbin_billing) / $t_global_billing * 100}")
if [ "$pct_faster" -gt 0 ]; then
echo " Winner: Per-Bin is ${ratio_billing}x faster (${pct_faster}% improvement)"
else
pct_slower=$(awk "BEGIN {printf \"%.0f\", ($t_perbin_billing - $t_global_billing) / $t_global_billing * 100}")
echo " Winner: Global is faster (per-bin ${pct_slower}% slower)"
fi
fi
echo ""
echo "HIGH CARDINALITY (session_id):"
echo " Global Top 9: ${ms_global_session}ms"
echo " Per-Bin Top 9: ${ms_perbin_session}ms"
if awk "BEGIN {exit !($t_global_session > 0 && $t_perbin_session > 0)}"; then
ratio_session=$(awk "BEGIN {printf \"%.2f\", $t_global_session / $t_perbin_session}")
pct_faster=$(awk "BEGIN {printf \"%.0f\", ($t_global_session - $t_perbin_session) / $t_global_session * 100}")
if [ "$pct_faster" -gt 0 ]; then
echo " Winner: Per-Bin is ${ratio_session}x faster (${pct_faster}% improvement)"
else
pct_slower=$(awk "BEGIN {printf \"%.0f\", ($t_perbin_session - $t_global_session) / $t_global_session * 100}")
echo " Winner: Global is faster (per-bin ${pct_slower}% slower)"
fi
fi
echo ""
# Cleanup
rm -f /tmp/benchmark_*.txt
rm -rf /tmp/benchmark_sql
echo "=== Done ==="