graphqlmetrics/migrations/20250612165114_drop_gql_metrics_operations.sql (17 lines of code) (raw):

-- migrate:up DROP TABLE IF EXISTS gql_metrics_operations; -- migrate:down CREATE TABLE IF NOT EXISTS gql_metrics_operations ( -- See https://github.com/PostHog/posthog/issues/10616 why ZSTD(3) is used Timestamp DateTime('UTC') CODEC(Delta, ZSTD(3)), OperationName LowCardinality(String) CODEC(ZSTD(3)), OperationHash LowCardinality(String) CODEC(ZSTD(3)), OperationType LowCardinality(String) CODEC(ZSTD(3)), -- query, mutation, subscription OperationContent String CODEC(ZSTD(3)), INDEX idx_operation_hash OperationHash TYPE bloom_filter(0.001) GRANULARITY 1, INDEX idx_operation_name OperationName TYPE bloom_filter(0.001) GRANULARITY 1, INDEX idx_operation_type OperationType TYPE bloom_filter(0.001) GRANULARITY 1, INDEX idx_operation_content OperationContent TYPE tokenbf_v1(32768, 3, 0) GRANULARITY 1 ) -- ReplacingMergeTree is used to avoid duplicates on the sorting key and keeps only the latest version -- https://altinity.com/blog/clickhouse-replacingmergetree-explained-the-good-the-bad-and-the-ugly -- Use FINAL as setting https://kb.altinity.com/engines/mergetree-table-engine-family/replacingmergetree/#final engine = ReplacingMergeTree(Timestamp) PARTITION BY toDate(Timestamp) -- Optimized for querying by OperationHash. If performance is bad for querying by OperationName, we can add -- a materialized view with the same data but with OperationName as the first sorting key. ORDER BY (OperationHash, OperationName, OperationType) -- We store operations for 90 days TTL toDateTime(Timestamp) + toIntervalDay(90) -- Keep index_granularity low to avoid too many parts on disk which will slow down point queries -- MergeTree works with sparse indexes. The index can't point to specific row, but to the block of rows. SETTINGS index_granularity = 512, ttl_only_drop_parts = 1;