Dhanesh Dhakrey
09/16/2026, 10:19 AMevents table has around 3*B events per month*, so I’m wondering whether this type of multi-stage query is realistically expected to work at this scale, and if so, what the recommended approach would be.
The query is essentially doing the following:
• Finding each user’s first APP_INSTALL event.
• Looking at their sessions in the following 7 days.
• Deduplicating sessions using ROW_NUMBER() because, for a given (session_id, platform), there can be multiple rows and we need to select the row with the highest event_count.
• Identifying users who were active on exactly 3 distinct days and had exactly 3 sessions during those 7 days.
• Finally, scanning their sessions again to find their last usage timestamp.
I’m using the multi-stage engine:
SET useMultistageEngine = true;
and the query currently times out even with:
OPTION(timeoutMs=90000);
My main questions are:
1. Can Pinot efficiently handle this type of query at this scale, or am I approaching it in the wrong way?
2. Would adding more/heavier indexes help here, or are the expensive parts mainly caused by the GROUP BY, window function, joins, COUNT(DISTINCT ...), and repeated scans of sessions?
3. What is the recommended way to plan indexing for a query like this? Should I first use something like EXPLAIN / query plan mode to understand which operators are expensive and then decide which columns/indexes to optimize?
4. Are there specific indexes or table/data-model changes that would make these joins and aggregations more efficient in Pinot?
5. Would it be better to pre-aggregate or maintain some of these metrics rather than calculating them at query time?
I’m particularly interested in understanding the right process for optimizing Pinot queries:
query plan → identify the expensive operators/scans → determine whether indexing can help → benchmark the change, rather than blindly adding indexes.
Here is the full query for reference:
SET useMultistageEngine = true;
WITH first_install AS (
SELECT
user_id,
MIN(event_timestamp) AS first_install_timestamp,
MIN(event_date_ist) AS first_install_date
FROM events
WHERE event_type = 'APP_INSTALL'
AND user_id IS NOT NULL
AND event_year = 2026
AND event_month = 9
GROUP BY user_id
),
ranked_sessions AS (
SELECT
s.*,
ROW_NUMBER() OVER (
PARTITION BY s.session_id, s.platform
ORDER BY s.event_count DESC
) AS rn
FROM sessions s
WHERE s.session_id IS NOT NULL
),
dedup_sessions AS (
SELECT
session_id,
platform,
user_id,
property_id,
event_count,
page_view_count,
min_timestamp,
max_timestamp,
min_date_ist
FROM ranked_sessions
WHERE rn = 1
),
sessions_7d AS (
SELECT
fi.user_id,
fi.first_install_timestamp,
fi.first_install_date,
s.session_id,
s.platform,
s.min_timestamp,
s.max_timestamp,
s.min_date_ist
FROM first_install fi
JOIN dedup_sessions s
ON fi.user_id = s.user_id
WHERE s.min_timestamp >= fi.first_install_timestamp
AND s.min_timestamp < fi.first_install_timestamp + 604800000
),
qualified_users AS (
SELECT
user_id,
MIN(first_install_timestamp) AS first_install_timestamp,
MIN(first_install_date) AS first_install_date,
COUNT(DISTINCT min_date_ist) AS active_days_7d,
COUNT(DISTINCT session_id) AS session_count_7d
FROM sessions_7d
GROUP BY user_id
HAVING COUNT(DISTINCT min_date_ist) = 3
AND COUNT(DISTINCT session_id) = 3
),
last_usage AS (
SELECT
s.user_id,
MAX(s.max_timestamp) AS last_used_timestamp
FROM dedup_sessions s
JOIN first_install fi
ON s.user_id = fi.user_id
GROUP BY s.user_id
)
SELECT
q.user_id,
q.first_install_date,
DATETIMECONVERT(
lu.last_used_timestamp,
'1:MILLISECONDS:EPOCH',
'1:DAYS:SIMPLE_DATE_FORMAT:yyyy-MM-dd tz(Asia/Kolkata)',
'1:DAYS'
) AS last_used_date,
q.active_days_7d,
q.session_count_7d
FROM qualified_users q
LEFT JOIN last_usage lu
ON q.user_id = lu.user_id
ORDER BY q.first_install_date
OPTION(timeoutMs=90000);Mayank
Gonzalo Ortiz
09/18/2026, 3:12 PMGonzalo Ortiz
09/18/2026, 3:18 PMGonzalo Ortiz
09/18/2026, 3:21 PMDhanesh Dhakrey
09/21/2026, 9:24 AM