-- ✅ 良い: ClickHouse固有の集計関数を使用SELECT
toStartOfDay(created_at) ASday,
market_id,
sum(volume) AS total_volume,
count() AS total_trades,
uniq(trader_id) AS unique_traders,
avg(trade_size) AS avg_size
FROM trades
WHERE created_at >= today() -INTERVAL7DAYGROUPBYday, market_id
ORDERBYdayDESC, total_volume DESC;
-- ✅ パーセンタイルにはquantileを使用(percentileより効率的)SELECT
quantile(0.50)(trade_size) AS median,
quantile(0.95)(trade_size) AS p95,
quantile(0.99)(trade_size) AS p99
FROM trades
WHERE created_at >= now() -INTERVAL1HOUR;
ウィンドウ関数
-- 累計計算SELECTdate,
market_id,
volume,
sum(volume) OVER (
PARTITIONBY market_id
ORDERBYdateROWSBETWEEN UNBOUNDED PRECEDING ANDCURRENTROW
) AS cumulative_volume
FROM markets_analytics
WHEREdate>= today() -INTERVAL30DAYORDERBY market_id, date;
-- 時間別統計のマテリアライズドビューを作成CREATE MATERIALIZED VIEW market_stats_hourly_mv
TO market_stats_hourly
ASSELECT
toStartOfHour(timestamp) AShour,
market_id,
sumState(amount) AS total_volume,
countState() AS total_trades,
uniqState(user_id) AS unique_users
FROM trades
GROUPBYhour, market_id;
-- マテリアライズドビューのクエリSELECThour,
market_id,
sumMerge(total_volume) AS volume,
countMerge(total_trades) AS trades,
uniqMerge(unique_users) AS users
FROM market_stats_hourly
WHEREhour>= now() -INTERVAL24HOURGROUPBYhour, market_id;
パフォーマンスモニタリング
クエリパフォーマンス
-- 低速クエリをチェックSELECT
query_id,
user,
query,
query_duration_ms,
read_rows,
read_bytes,
memory_usage
FROM system.query_log
WHERE type ='QueryFinish'AND query_duration_ms >1000AND event_time >= now() -INTERVAL1HOURORDERBY query_duration_ms DESC
LIMIT 10;
テーブル統計
-- テーブルサイズをチェックSELECT
database,
table,
formatReadableSize(sum(bytes)) AS size,
sum(rows) ASrows,
max(modification_time) AS latest_modification
FROM system.parts
WHERE active
GROUPBY database, tableORDERBYsum(bytes) DESC;
一般的な分析クエリ
時系列分析
-- 日次アクティブユーザーSELECT
toDate(timestamp) ASdate,
uniq(user_id) AS daily_active_users
FROM events
WHEREtimestamp>= today() -INTERVAL30DAYGROUPBYdateORDERBYdate;
-- リテンション分析SELECT
signup_date,
countIf(days_since_signup =0) AS day_0,
countIf(days_since_signup =1) AS day_1,
countIf(days_since_signup =7) AS day_7,
countIf(days_since_signup =30) AS day_30
FROM (
SELECT
user_id,
min(toDate(timestamp)) AS signup_date,
toDate(timestamp) AS activity_date,
dateDiff('day', signup_date, activity_date) AS days_since_signup
FROM events
GROUPBY user_id, activity_date
)
GROUPBY signup_date
ORDERBY signup_date DESC;
ファネル分析
-- コンバージョンファネルSELECT
countIf(step ='viewed_market') AS viewed,
countIf(step ='clicked_trade') AS clicked,
countIf(step ='completed_trade') AS completed,
round(clicked / viewed *100, 2) AS view_to_click_rate,
round(completed / clicked *100, 2) AS click_to_completion_rate
FROM (
SELECT
user_id,
session_id,
event_type AS step
FROM events
WHERE event_date = today()
)
GROUPBY session_id;
コホート分析
-- サインアップ月別のユーザーコホートSELECT
toStartOfMonth(signup_date) AS cohort,
toStartOfMonth(activity_date) ASmonth,
dateDiff('month', cohort, month) AS months_since_signup,
count(DISTINCT user_id) AS active_users
FROM (
SELECT
user_id,
min(toDate(timestamp)) OVER (PARTITIONBY user_id) AS signup_date,
toDate(timestamp) AS activity_date
FROM events
)
GROUPBY cohort, month, months_since_signup
ORDERBY cohort, months_since_signup;