Mapping & Dynamic Mapping
Chào bạn, tiếp nối chuỗi kiến thức về Elasticsearch cho Senior Backend Engineer, chúng ta sẽ đi vào phần xương sống của việc lưu trữ dữ liệu: Mapping.
Nếu coi Elasticsearch như một database (dù không nên dùng nó làm primary DB), thì Mapping chính là Schema (DDL) trong SQL.
Hiểu sai về Mapping là nguyên nhân hàng đầu gây ra các vấn đề về hiệu năng (Performance), tốn dung lượng ổ cứng (Storage Bloat), và lỗi "Field type mismatch" khi chạy Production.
1. Mapping là gì?
Mapping là quá trình định nghĩa:
Các field (trường) nào có trong document.
Kiểu dữ liệu của từng field (Text, Keyword, Integer, Date, Object...).
Cách dữ liệu được đánh index và phân tích (Analyzer nào được dùng).
Có 2 loại Mapping: Dynamic Mapping (Tự động) và Explicit Mapping (Thủ công).
2. Dynamic Mapping (Sự tiện lợi và "Cái bẫy")
Khi bạn đẩy (index) một document JSON vào ES mà chưa định nghĩa Mapping trước, ES sẽ tự động đoán kiểu dữ liệu dựa trên giá trị của field đó.
Cơ chế đoán (Type Inference):
"10"(String) ->text+keyword(ES tạo cả 2 field con).10(Number) ->long.10.5(Float) ->float."2024-01-01"(String date) ->date.true->boolean.
Tại sao KHÔNG NÊN dùng Dynamic Mapping ở Production?
Là Senior Engineer, bạn cần kiểm soát hệ thống. Dynamic Mapping mang lại sự khó lường:
Sai kiểu dữ liệu (Type Mismatch):
Doc 1:
{"price": 100}-> ES mappricelàlong.Doc 2:
{"price": 100.5}-> LỖI! ES từ chối nhận Doc 2 vì100.5không nhét vừa vàolong. Bạn mất dữ liệu.
Lãng phí tài nguyên (Wasteful Storage):
Với mọi chuỗi String (ví dụ:
status: "active"), Dynamic Mapping mặc định tạo ra 2 trường:status(typetext): Để search full-text (dư thừa nếu bạn chỉ cần lọc chính xác).status.keyword(typekeyword): Để filter/agg.
Điều này làm gấp đôi dung lượng index và index chậm hơn.
Mapping Explosion (Bùng nổ Mapping):
Nếu bạn log một object JSON động mà key thay đổi liên tục, ES sẽ tạo field mới cho mỗi key. Quá nhiều field (>1000) sẽ làm đầy Cluster State (bộ nhớ quản lý trạng thái cluster), gây treo cả Cluster.
3. Explicit Mapping (Cách làm chuẩn mực)
Bạn nên tự định nghĩa Mapping (thường thông qua Index Templates) để tối ưu hóa.
Ví dụ một Mapping tối ưu cho Product:
JSON
Các thông số tối ưu (Senior Tips):
index: false: Lưu field này trong_sourceđể hiển thị, nhưng không đánh index. Dùng cho các field chỉ để xem, không bao giờ search (ví dụ: URL ảnh thumb). Tiết kiệm rất nhiều dung lượng.norms: false: Tắt lưu trữ chuẩn hóa độ dài. Dùng cho fieldtexthoặckeywordmà bạn không quan tâm đến điểm số (scoring) - tức là chỉ filter yes/no.doc_values: false: Tắt cấu trúc cột (columnar store). Nếu bạn chắc chắn không bao giờ sort hoặc aggregate trên field này, hãy tắt nó để giảm I/O khi ghi.enabled: false: ES lưu JSON gốc nhưng bỏ qua hoàn toàn việc parsing field này. Tuyệt vời cho các cục log JSON lồng nhau phức tạp mà bạn chỉ muốn lấy ra xem chứ không query.
4. Sự thật phũ phàng: Immutability (Bất biến)
Đây là điều đau đầu nhất với người mới dùng ES: Bạn KHÔNG THỂ sửa đổi Mapping của một field đã tồn tại.
Tại sao? Vì dữ liệu đã được ghi vào Inverted Index theo kiểu cũ rồi. Nếu sửa mapping (ví dụ từ
textsanglong), Index cũ sẽ trở nên vô nghĩa và không đọc được.
Giải pháp khi cần đổi Mapping:
Tạo Index mới (v1 -> v2) với Mapping đúng.
Dùng Reindex API để copy dữ liệu từ Index cũ sang mới.
Dùng Alias (bí danh) để trỏ ứng dụng sang Index mới (Zero downtime).
Tóm lại
Dynamic Mapping: Tốt cho Dev/Test, tồi cho Prod.
Explicit Mapping: Bắt buộc cho Prod để tối ưu Storage/CPU.
Chiến lược: Luôn định nghĩa
typerõ ràng. Cái gì không search ->index: false. Cái gì không cần score ->norms: false.
Last updated