Sooq Analytics event store
Sooq Analytics (fictional) · 4 tables · 420,200 rows · version 1
Large tables for query-performance lessons: 20,000 users, 300,000 tracking events and 100,000 orders during 2025, plus a small product list. Only primary keys are indexed, so filters and joins on other columns start as sequential scans; you create the indexes and compare plans. Columns are chosen to show selectivity: email is almost unique, status is dominated by one value, and event_type and user activity are heavily skewed.
The documentation is open to everyone. Querying this dataset in the playground is included with Formula Quest membership; lessons that use it follow their own access.
Relationships
Sample queries
EXPLAIN
SELECT *
FROM users
WHERE email = 'user12345@example.net';EXPLAIN ANALYZE
SELECT event_type, count(*)
FROM events
WHERE user_id = 42
GROUP BY event_type;EXPLAIN
SELECT order_id, user_id, amount
FROM orders
WHERE status = 'pending';SELECT event_type, count(*) AS events,
round(100.0 * count(*) / sum(count(*)) OVER (), 1) AS pct
FROM events
GROUP BY event_type
ORDER BY events DESC;SELECT occurred_at::date AS day, count(*) AS purchases
FROM events
WHERE event_type = 'purchase'
AND occurred_at >= '2025-03-01' AND occurred_at < '2025-04-01'
GROUP BY day
ORDER BY day;Data dictionary
products
200 rows · primary key (product_id)Products sold on the marketplace (small lookup table).
| Column | Type | Null? | Key | Description |
|---|---|---|---|---|
| product_id | integer | no | PK | Unique product number. |
| product_name | text | no | Product name. | |
| category | text | no | Product category (10 categories). | |
| price | numeric(12,2) | no | Unit price in SAR. |
users
20,000 rows · primary key (user_id)Registered marketplace users (20,000). Only user_id is indexed.
| Column | Type | Null? | Key | Description |
|---|---|---|---|---|
| user_id | integer | no | PK | Unique user number. Users were numbered in signup order. |
| text | no | Email address. Unique in practice, but there is no unique constraint or index (high selectivity). | ||
| full_name | text | no | User's name (many users share a name). | |
| country | char(2) | no | ISO country code; about 60% are SA. | |
| plan | text | no | Subscription plan: free (about 80%), plus or pro. | |
| signup_at | timestamp | no | When the user registered (2021–2024). | |
| last_login_at | timestamp | yes | Most recent login during 2025. NULL if the user never logged in. |
events
300,000 rows · primary key (event_id)Tracking events (300,000) recorded during 2025, inserted in time order. Only event_id is indexed.
| Column | Type | Null? | Key | Description |
|---|---|---|---|---|
| event_id | bigint | no | PK | Unique event number, increasing with time. |
| user_id | integer | no | users.user_id | User who triggered the event. Not indexed; a few power users have thousands of events. |
| event_type | text | no | page_view (about 70%), click, search, add_to_cart, checkout_start, purchase, login or refund (rare). Skewed. | |
| occurred_at | timestamp | no | When the event happened (2025, UTC). Increases with event_id. | |
| country | char(2) | no | Country the event came from (usually the user's country). | |
| device | text | no | mobile, desktop or tablet. | |
| properties | text | no | Extra details as JSON text, e.g. {"page": "/p/12", "session": 81}. Cast to jsonb to query it. |
orders
100,000 rows · primary key (order_id)Marketplace orders (100,000) placed during 2025. Only order_id is indexed.
| Column | Type | Null? | Key | Description |
|---|---|---|---|---|
| order_id | integer | no | PK | Unique order number, increasing with time. |
| user_id | integer | no | users.user_id | User who placed the order. Not indexed. |
| product_id | integer | no | products.product_id | Product ordered. Not indexed. |
| quantity | smallint | no | Units ordered (1–3). | |
| amount | numeric(12,2) | no | Order value in SAR (price × quantity). | |
| status | text | no | completed (about 95%), pending, cancelled or refunded. Low selectivity. | |
| created_at | timestamp | no | When the order was placed (2025, UTC). | |
| coupon_code | text | yes | Coupon used. NULL for most orders. |