Elasticsearch Bài học 36: Metric Aggregations - Tính Min, Max, Avg, Sum và Cardinality
Kế thừa tư duy từ Bài 35, chúng ta sẽ bắt tay vào nhóm Aggregations cơ bản nhất: Metric. Nhóm này sinh ra để thực hiện các phép toán thống kê trên các trường dạng số (Numeric) hoặc đếm số lượng trên các trường keyword.
Nếu coi Bucket Aggregations là việc "chia dữ liệu vào các rổ", thì Metric Aggregations chính là việc "đếm và đo lường đồ vật bên trong từng cái rổ đó".
1. Bộ tứ cơ bản: Min, Max, Avg và Sum
Đây là sự thay thế hoàn hảo cho các hàm toán học kinh điển trong SQL. Giả sử hệ thống Hasaki cần báo cáo: "Trong danh mục Chăm sóc da, giá trung bình là bao nhiêu, và tính tổng giá trị tồn kho (giả định dùng trường price cho nhanh)?"
SQL Tương đương:
SQL
SELECT MIN(price), MAX(price), AVG(price), SUM(price)
FROM products
WHERE category = 'Chăm sóc da mặt';
Cú pháp Elasticsearch:
JSON
GET products/_search
{
"size": 0,
"query": {
"match": { "category": "Chăm sóc da mặt" }
},
"aggs": {
"gia_thap_nhat": { "min": { "field": "price" } },
"gia_cao_nhat": { "max": { "field": "price" } },
"gia_trung_binh": { "avg": { "field": "price" } },
"tong_gia_tri": { "sum": { "field": "price" } }
}
}
Kết quả trả về sẽ nằm gọn gàng trong một block aggregations:
JSON
"aggregations": {
"gia_thap_nhat": { "value": 150000.0 },
"gia_cao_nhat": { "value": 3500000.0 },
"gia_trung_binh": { "value": 450000.5 },
"tong_gia_tri": { "value": 1250000000.0 }
}
(Lưu ý: Luôn nhớ tham số "size": 0 ở gốc để không bắt Elasticsearch gửi kèm hàng ngàn Document JSON vô ích về Backend).
2. Đường tắt tối ưu: Hàm stats
Việc phải gõ 4 khối lệnh riêng biệt cho 4 phép toán cơ bản đôi khi làm phình to payload JSON. Elasticsearch cung cấp một Metric gộp mang tên stats.
Chỉ với một khai báo duy nhất:
JSON
"aggs": {
"thong_ke_gia": {
"stats": { "field": "price" }
}
}
Hệ thống sẽ trả về đồng thời 5 chỉ số: count (tổng số record), min, max, avg, và sum.
Nếu team Data Analytics yêu cầu các chỉ số phức tạp hơn như Phương sai (Variance) hay Độ lệch chuẩn (Standard Deviation) để vẽ biểu đồ phân phối, bạn chỉ cần thay stats thành extended_stats. Cỗ máy toán học của Elasticsearch sẽ lo toàn bộ.
3. cardinality: Lời giải cho bài toán COUNT(DISTINCT)
Đây là Metric quan trọng nhất và chứa nhiều cạm bẫy thiết kế nhất mà một Backend Engineer cần nắm.
Nghiệp vụ thực tế: Hệ thống soát vé AFC của bạn ghi nhận 5 triệu lượt quẹt thẻ mỗi ngày. Sếp yêu cầu: "Hôm nay có bao nhiêu HÀNH KHÁCH DUY NHẤT (dựa trên card_id) đi tàu?"
SQL: SELECT COUNT(DISTINCT card_id) FROM afc_logs;
Vấn đề của hệ thống phân tán:
Để đếm chính xác 100% số lượng phần tử duy nhất trên một bảng 5 triệu dòng ở MySQL, database phải nạp toàn bộ danh sách ID vào RAM, loại bỏ trùng lặp (deduplication) rồi mới đếm. Chạy lệnh này trên SQL cực kỳ chậm và tốn RAM.
Với Elasticsearch, dữ liệu lại còn bị băm ra 5 Shard khác nhau. Việc mang toàn bộ danh sách card_id từ 5 server gom về Coordinating Node để đếm tập hợp (Set) sẽ gây ra thảm họa OOM (Tràn RAM) ngay lập tức.
Giải pháp của Elasticsearch: Thuật toán HyperLogLog++
Khi bạn gọi hàm cardinality, Elasticsearch không đếm chính xác 100%. Nó sử dụng thuật toán xấp xỉ xác suất (Probabilistic algorithm) mang tên HyperLogLog++.
Nó băm (hash) các giá trị card_id, kiểm tra các bit nhị phân và ước lượng ra số lượng phần tử duy nhất. Nhờ vậy, nó có thể đếm hàng tỷ phần tử mà chỉ tốn vài chục Megabyte RAM với tốc độ chớp nhoáng.
Cú pháp:
JSON
GET afc_logs/_search
{
"size": 0,
"aggs": {
"so_khach_duy_nhat": {
"cardinality": {
"field": "card_id.keyword",
"precision_threshold": 3000
}
}
}
}
Tham số sinh tử: precision_threshold
Thuật toán này là một sự đánh đổi giữa Bộ nhớ RAM và Độ chính xác (Accuracy).
-
precision_thresholdcho phép bạn định nghĩa: "Tôi muốn kết quả đếm chính xác 100% cho đến ngưỡng nào?". -
Mặc định là
3000. Nghĩa là nếu số lượng thẻ duy nhất , kết quả đảm bảo chính xác tuyệt đối. Vượt qua 3000, nó bắt đầu sai số khoảng 1-5%. -
Bạn có thể tăng con số này lên tối đa 40000. Càng tăng, kết quả càng chính xác (sai số giảm), nhưng lượng RAM ngốn sẽ tỷ lệ thuận theo.
Tư duy Kiến trúc sư: Trong báo cáo Big Data, việc đếm được "Có khoảng 1.250.000 khách" hay "Có 1.250.043 khách" không tạo ra sự khác biệt về mặt quyết định kinh doanh (Business Decision). Hãy chấp nhận sai số vài phần trăm để đổi lấy tốc độ và sự ổn định của hệ thống. Đừng cố gắng tìm cách đếm chính xác 100% hàng triệu ID phân tán.
Metric Aggregations chỉ trả về 1 con số vô tri (Ví dụ: Tổng doanh thu là 10 tỷ). Để bản báo cáo có ý nghĩa, ta phải bổ dọc con số 10 tỷ đó ra: Bao nhiêu từ Cetaphil, Bao nhiêu từ L'Oreal?
Đó là lúc chúng ta phải triệu hồi sức mạnh chia giỏ của Bucket Aggregations.
All rights reserved