Skip to content

Commit 3f3321e

Browse files
committed
feat: new operation rollups using quantilesTDigest and dedicated views with less dimensions for unfiltered queries for less row reads and faster speed
1 parent 6489fc6 commit 3f3321e

2 files changed

Lines changed: 123 additions & 0 deletions

File tree

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import type { Action } from '../clickhouse';
2+
3+
const aggregateColumns = `
4+
total UInt32 CODEC(T64, ZSTD(1)),
5+
total_ok UInt32 CODEC(T64, ZSTD(1)),
6+
duration_avg AggregateFunction(avg, UInt64) CODEC(ZSTD(1)),
7+
duration_quantiles AggregateFunction(quantilesTDigest(0.75, 0.9, 0.95, 0.99), UInt64) CODEC(ZSTD(1))
8+
`;
9+
10+
const aggregateStates = `
11+
CAST(count() AS UInt32) AS total,
12+
CAST(sum(ok) AS UInt32) AS total_ok,
13+
avgState(duration) AS duration_avg,
14+
quantilesTDigestState(0.75, 0.9, 0.95, 0.99)(duration) AS duration_quantiles
15+
`;
16+
17+
const createRollups = async (
18+
exec: (query: string) => Promise<void>,
19+
granularity: 'minutely' | 'hourly' | 'daily',
20+
bucket: 'toStartOfMinute' | 'toStartOfHour' | 'toStartOfDay',
21+
partitionBy: string,
22+
ttlInterval: string,
23+
) => {
24+
const table = `operations_v01_${granularity}`;
25+
26+
await exec(`
27+
CREATE TABLE IF NOT EXISTS default.${table}
28+
(
29+
target LowCardinality(String) CODEC(ZSTD(1)),
30+
timestamp DateTime('UTC') CODEC(DoubleDelta, LZ4),
31+
hash String CODEC(ZSTD(1)),
32+
client_name String CODEC(ZSTD(1)),
33+
client_version String CODEC(ZSTD(1)),
34+
${aggregateColumns}
35+
)
36+
ENGINE = SummingMergeTree
37+
PARTITION BY ${partitionBy}
38+
PRIMARY KEY (target, hash)
39+
ORDER BY (target, hash, client_name, client_version, timestamp)
40+
TTL timestamp + INTERVAL ${ttlInterval}
41+
SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1
42+
`);
43+
44+
await exec(`
45+
CREATE MATERIALIZED VIEW IF NOT EXISTS default.${table}_mv TO default.${table}
46+
AS (
47+
SELECT
48+
target,
49+
${bucket}(timestamp) AS timestamp,
50+
hash,
51+
client_name,
52+
client_version,
53+
${aggregateStates}
54+
FROM default.operations
55+
GROUP BY target, hash, client_name, client_version, timestamp
56+
)
57+
`);
58+
59+
await exec(`
60+
CREATE TABLE IF NOT EXISTS default.${table}_by_timestamp
61+
(
62+
target LowCardinality(String) CODEC(ZSTD(1)),
63+
timestamp DateTime('UTC') CODEC(DoubleDelta, LZ4),
64+
${aggregateColumns}
65+
)
66+
ENGINE = SummingMergeTree
67+
PARTITION BY ${partitionBy}
68+
PRIMARY KEY (target, timestamp)
69+
ORDER BY (target, timestamp)
70+
TTL timestamp + INTERVAL ${ttlInterval}
71+
SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1
72+
`);
73+
74+
await exec(`
75+
CREATE MATERIALIZED VIEW IF NOT EXISTS default.${table}_by_timestamp_mv TO default.${table}_by_timestamp
76+
AS (
77+
SELECT
78+
target,
79+
${bucket}(timestamp) AS timestamp,
80+
${aggregateStates}
81+
FROM default.operations
82+
GROUP BY target, timestamp
83+
)
84+
`);
85+
86+
await exec(`
87+
CREATE TABLE IF NOT EXISTS default.${table}_by_client
88+
(
89+
target LowCardinality(String) CODEC(ZSTD(1)),
90+
client_name String CODEC(ZSTD(1)),
91+
client_version String CODEC(ZSTD(1)),
92+
timestamp DateTime('UTC') CODEC(DoubleDelta, LZ4),
93+
${aggregateColumns}
94+
)
95+
ENGINE = SummingMergeTree
96+
PARTITION BY ${partitionBy}
97+
PRIMARY KEY (target, client_name, client_version, timestamp)
98+
ORDER BY (target, client_name, client_version, timestamp)
99+
TTL timestamp + INTERVAL ${ttlInterval}
100+
SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1
101+
`);
102+
103+
await exec(`
104+
CREATE MATERIALIZED VIEW IF NOT EXISTS default.${table}_by_client_mv TO default.${table}_by_client
105+
AS (
106+
SELECT
107+
target,
108+
client_name,
109+
client_version,
110+
${bucket}(timestamp) AS timestamp,
111+
${aggregateStates}
112+
FROM default.operations
113+
GROUP BY target, client_name, client_version, timestamp
114+
)
115+
`);
116+
};
117+
118+
export const action: Action = async exec => {
119+
await createRollups(exec, 'minutely', 'toStartOfMinute', 'toStartOfHour(timestamp)', '24 HOUR');
120+
await createRollups(exec, 'hourly', 'toStartOfHour', 'toYYYYMMDD(timestamp)', '30 DAY');
121+
await createRollups(exec, 'daily', 'toStartOfDay', 'toYYYYMM(timestamp)', '1 YEAR');
122+
};

packages/migrations/src/clickhouse.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ export async function migrateClickHouse(
185185
import('./clickhouse-actions/019-metric-alert-target-daily-rollup'),
186186
import('./clickhouse-actions/020-usage-coordinate-counts'),
187187
import('./clickhouse-actions/021-usage-coordinate-errors'),
188+
import('./clickhouse-actions/022-operation-v01-rollups'),
188189
]);
189190

190191
async function actionRunner(action: Action, index: number) {

0 commit comments

Comments
 (0)