Ví dụ dùng bảng telemetry.interfaces (counter in_octets, cột time, source, name) và logs.syslog định nghĩa trong ClickHouse schema và TTL. Query top talkers cho flow xem ClickHouse top talkers.
Hàm thời gian
| Mục đích | Biểu thức |
|---|---|
| Bây giờ / hôm nay | now(), now64(3), today() |
| Khoảng tương đối | time > now() - INTERVAL 15 MINUTE |
| Gom theo khoảng bất kỳ | toStartOfInterval(time, INTERVAL 5 MINUTE) |
| Gom theo phút / 5 phút / giờ / ngày | toStartOfMinute(t), toStartOfFiveMinutes(t), toStartOfHour(t), toDate(t) |
| Đổi múi giờ hiển thị | toTimeZone(time, 'Asia/Ho_Chi_Minh') |
| Chuỗi → DateTime | toDateTime('2026-11-06 08:00:00', 'Asia/Ho_Chi_Minh'), parseDateTimeBestEffort('2026-11-06T01:02:03Z') |
| Unix timestamp | toUnixTimestamp(time), toDateTime(1730851200) |
| Hiệu hai mốc | dateDiff('second', t1, t2) |
| Định dạng | formatDateTime(time, '%Y-%m-%d %H:%i') (%i là phút; %M ở bản mới là tên tháng) |
| Macro Grafana | WHERE $__timeFilter(time) |
Aggregate hay dùng
| Mục đích | Biểu thức |
|---|---|
| Percentile | quantile(0.95)(bps) |
| Nhiều percentile một lần | quantiles(0.5, 0.95, 0.99)(bps) (trả mảng) |
| Percentile chính xác (tốn RAM) | quantileExact(0.99)(bps) |
| Đếm có điều kiện | countIf(severity IN ('err', 'crit')) |
| Tổng có điều kiện | sumIf(cnt, mnemonic = 'ADJCHANGE') |
| Đếm giá trị khác nhau (xấp xỉ / chính xác) | uniq(source) / uniqExact(source) |
| Giá trị mới nhất theo thời gian | argMax(in_octets, time) |
| N giá trị xuất hiện nhiều nhất (xấp xỉ) | topK(5)(mnemonic) |
| Gom thành mảng | groupArray(name), groupUniqArray(source) |
| Điều kiện nhiều nhánh | multiIf(bps > 9e9, 'high', bps > 1e9, 'mid', 'low') |
bps từ counter (window function)
SELECT time, source, name,
(in_octets - prev_octets) * 8 / dateDiff('second', prev_time, time) AS bps
FROM
(
SELECT time, source, name, in_octets,
lagInFrame(in_octets) OVER w AS prev_octets,
lagInFrame(time) OVER w AS prev_time
FROM telemetry.interfaces
WHERE source = 'pe1-hni' AND time > now() - INTERVAL 1 HOUR
WINDOW w AS (PARTITION BY source, name ORDER BY time ROWS BETWEEN 1 PRECEDING AND CURRENT ROW)
)
WHERE prev_time > toDateTime(0) -- bỏ dòng đầu mỗi interface (không có mẫu trước)
AND in_octets >= prev_octets -- bỏ điểm counter reset
ORDER BY name, time;p95 bps theo interface trong 1 ngày: bọc query trên (đổi khoảng thời gian thành INTERVAL 1 DAY) rồi SELECT source, name, quantile(0.95)(bps) ... GROUP BY source, name.
Lấp khoảng trống bằng WITH FILL
Phút không có log sẽ không có dòng, đồ thị bị nối thẳng. WITH FILL thêm dòng giá trị mặc định (0):
SELECT toStartOfInterval(toDateTime(timestamp), INTERVAL 1 MINUTE) AS t, count() AS n
FROM logs.syslog
WHERE timestamp > now() - INTERVAL 1 HOUR AND source = 'pe1-hni'
GROUP BY t
ORDER BY t WITH FILL
FROM toStartOfInterval(now() - INTERVAL 1 HOUR, INTERVAL 1 MINUTE)
TO now()
STEP INTERVAL 1 MINUTE;Kiểu của FROM/TO phải khớp kiểu cột t (ở đây DateTime, nên bọc toDateTime(...) cho cột DateTime64).
Mảng và arrayJoin
| Mục đích | Biểu thức |
|---|---|
| Sinh nhiều dòng từ mảng | SELECT arrayJoin(['pe1-hni', 'pe2-hcm']) AS source |
| Tách chuỗi thành mảng | splitByChar(',', 'ge-0/0/0,ge-0/0/1') |
| Lấy mọi chuỗi khớp regex | extractAll(message, '\\d+\\.\\d+\\.\\d+\\.\\d+') |
| Lọc / biến đổi phần tử | arrayFilter(x -> x > 0, arr), arrayMap(x -> x * 8, arr) |
| Có chứa phần tử | has(arr, 'ADJCHANGE') |
| Độ dài, phần tử đầu (index từ 1) | length(arr), arr[1] |
IP nào xuất hiện nhiều nhất trong syslog 1 giờ qua (mỗi IP trong một dòng log thành một dòng kết quả):
SELECT arrayJoin(extractAll(message, '\\d+\\.\\d+\\.\\d+\\.\\d+')) AS ip, count() AS n
FROM logs.syslog
WHERE timestamp > now() - INTERVAL 1 HOUR
GROUP BY ip ORDER BY n DESC LIMIT 10;Chuỗi và IP
| Mục đích | Biểu thức |
|---|---|
| Lấy nhóm regex đầu tiên | extract(message, 'neighbor (\\S+)') |
| Khớp regex (RE2) | match(message, 'BGP.*(Down|Idle)') |
| LIKE không phân biệt hoa thường | message ILIKE '%adjchange%' |
| Thay theo regex | replaceRegexpAll(name, '^HundredGigE', 'Hu') |
| IP thuộc dải | isIPAddressInRange(source_ip, '198.51.100.0/24') |
| Chuỗi ↔ kiểu IPv4 | toIPv4('198.51.100.1'), IPv4NumToString(ip) |
clickhouse-client
| Mục đích | Lệnh |
|---|---|
| Chạy một query | clickhouse-client --host ch.example.net -q "SELECT count() FROM logs.syslog" |
| Xuất CSV có header | clickhouse-client -q "SELECT * FROM logs.syslog LIMIT 1000 FORMAT CSVWithNames" > out.csv |
| Tham số an toàn (tránh ghép chuỗi) | clickhouse-client --param_dev=pe1-hni -q "SELECT count() FROM logs.syslog WHERE source = {dev:String}" |
| Nạp CSV vào bảng | clickhouse-client -q "INSERT INTO telemetry.interfaces FORMAT CSVWithNames" < data.csv |
| Chạy file nhiều câu lệnh | clickhouse-client --multiquery < schema.sql |
| Xem dòng theo chiều dọc | thêm FORMAT Vertical (hoặc kết thúc bằng \G trong client) |
| Query file CSV không cần server | clickhouse-local -q "SELECT count() FROM file('out.csv', CSVWithNames)" |
Chuỗi trong ClickHouse dùng nháy đơn và backslash phải gấp đôi: regex \d viết là '\\d'.