カーディナリティ順に並べる (低い順から高い順)
時間粒度は重要です
ORDER BY 句でタイムスタンプを使用する場合は、カーディナリティと精度のトレードオフを考慮してください。マイクロ秒精度のタイムスタンプは非常に高いカーディナリティ (ほぼ各行が一意の値を持つ状態) を生み、ClickHouse のスパースプライマリインデックスの有効性を低下させます。タイムスタンプを丸めるとカーディナリティが低くなるため、より効果的にインデックススキップを行える一方、時間ベースのクエリでは精度が失われます。
runnable editable
平均値ではなく、個々のクエリに注目する
メモリと行スキャン
GROUP BY user_id, error_message, url_path のようなクエリでは、3つの値の一意な組み合わせごとに個別のメモリ状態が作られます。ユーザー数、エラー種別、URLパスが増えると、メモリ上に同時に保持しなければならない集計状態が、簡単に数百万件に達する可能性があります。
極端なケースでは、Sentryは決定論的サンプリングを使用します。10%にサンプリングすると、ほとんどの集計でおおむね5%の精度を維持したまま、メモリ使用量を90%削減できます。
cityHash64() が同じ入力に対して常に同じハッシュ値を生成することです。そのため、user_id = 12345 は常に同じ値にハッシュされ、そのユーザーは 10% のサンプルに毎回含まれるか、まったく含まれないかのいずれかになります。クエリごとに含まれたり含まれなかったりすることはありません。
Sentry のビットマスク最適化
関連ビデオ
- Lost in the Haystack - Optimizing High Cardinality Aggregations - Sentryの本番環境でのメモリ最適化から得られた知見
- ClickHouse Performance Analysis - Alexey Milovidovによるデバッグ手法の解説
- ClickHouse Meetup: Query Optimization Techniques - コミュニティによるクエリ最適化の戦略