Skip to content

Commit f88b467

Browse files
authored
chunk migration scripts (#96)
1 parent 1e1d11a commit f88b467

1 file changed

Lines changed: 34 additions & 14 deletions

File tree

packages/db/code-migrations/9-events-daily-stats.ts

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -151,35 +151,52 @@ export async function up() {
151151
console.log(` Backfill Start: ${startDate.toISOString().split('T')[0]}`);
152152
console.log(` Backfill End: ${endDate.toISOString().split('T')[0]} (inclusive)`);
153153
console.log(` Backfill Days: ${backfillDays} days`);
154+
console.log(` Chunking: Hourly (24 chunks per day)`);
155+
console.log(` Total Chunks: ${backfillDays * 24} hourly inserts`);
154156
console.log(` Total Events: ${totalEvents.toLocaleString()} in events table`);
155157
console.log('========================================');
156158
console.log('');
157159

158-
// Generate day-by-day INSERT statements with proper GROUP BY
160+
// Generate INSERT statements chunked by hour to reduce memory usage
161+
// Process each day in 24 hourly chunks to avoid ClickHouse memory limits
159162
const backfillSqls: string[] = [];
160163

161164
let currentDate = new Date(startDate); // Start from startDate (go forward)
162165

163166
while (currentDate <= endDate) {
164167
const dateStr = currentDate.toISOString().split('T')[0];
165168

166-
const sql = `INSERT INTO ${targetTable}
167-
SELECT
168-
project_id,
169-
name,
170-
toDate(created_at) as date,
171-
uniqState(profile_id) as unique_profiles_state,
172-
uniqState(session_id) as unique_sessions_state,
173-
countState() as event_count
174-
FROM events
175-
WHERE toDate(created_at) = '${dateStr}'
176-
GROUP BY project_id, name, date`;
169+
// Process each day in 24 hourly chunks
170+
for (let hour = 0; hour < 24; hour++) {
171+
const hourStart = `${dateStr} ${String(hour).padStart(2, '0')}:00:00`;
172+
const hourEnd = `${dateStr} ${String(hour).padStart(2, '0')}:59:59`;
173+
174+
const sql = `INSERT INTO ${targetTable}
175+
SELECT
176+
project_id,
177+
name,
178+
toDate(created_at) as date,
179+
uniqState(profile_id) as unique_profiles_state,
180+
uniqState(session_id) as unique_sessions_state,
181+
countState() as event_count
182+
FROM events
183+
WHERE created_at >= toDateTime('${hourStart}')
184+
AND created_at <= toDateTime('${hourEnd}')
185+
GROUP BY project_id, name, date`;
186+
187+
backfillSqls.push(sql);
188+
}
177189

178-
backfillSqls.push(sql);
179190
currentDate.setDate(currentDate.getDate() + 1);
180191
}
181192

182193
sqls.push(...backfillSqls);
194+
195+
// Add OPTIMIZE TABLE to merge hourly chunks into daily aggregates
196+
const optimizeSql = `OPTIMIZE TABLE ${targetTable} FINAL`;
197+
sqls.push(optimizeSql);
198+
console.log('Added OPTIMIZE TABLE command to merge hourly chunks');
199+
console.log('');
183200
} else {
184201
console.log('No data found in the specified date range, skipping backfill');
185202
}
@@ -204,10 +221,13 @@ export async function up() {
204221
const mvOpsTotal = sqls.filter(sql => sql.includes('CREATE') || sql.includes('MATERIALIZED VIEW')).length;
205222
const insertOpsTotal = sqls.filter(sql => sql.includes('INSERT')).length;
206223

224+
const optimizeOpsTotal = sqls.filter(sql => sql.includes('OPTIMIZE')).length;
225+
207226
console.log(`Generated ${sqls.length} SQL statements:`);
208227
console.log(` - ${deleteOpsTotal} DELETE operations (day-by-day)`);
209228
console.log(` - ${mvOpsTotal} MV creation operations`);
210-
console.log(` - ${insertOpsTotal} INSERT operations (day-by-day)`);
229+
console.log(` - ${insertOpsTotal} INSERT operations (hourly chunks)`);
230+
console.log(` - ${optimizeOpsTotal} OPTIMIZE operations (merge chunks)`);
211231
console.log(`SQL written to: ${sqlFilePath}`);
212232
console.log('');
213233

0 commit comments

Comments
 (0)