Logfire tăng tốc truy vấn JSON lên gấp 1.000 lần nhờ kỹ thuật 'dynamic shredding'
Pydantic vừa công bố kỹ thuật tối ưu mới mang tên dynamic shredding cho nền tảng quan sát Logfire, giúp các truy vấn trên dữ liệu bán cấu trúc nhanh hơn tới 1.000 lần. Những truy vấn trước đây mất 30 giây hoặc timeout nay hoàn tất trong chưa đầy một giây, nhờ tự động tách các thuộc tính JSON được truy vấn nhiều nhất thành các cột riêng có kiểu dữ liệu chặt chẽ.

Logfire tăng tốc truy vấn JSON lên gấp 1.000 lần nhờ kỹ thuật "dynamic shredding"
Pydantic vừa công bố một bước tiến lớn trong cách Logfire xử lý dữ liệu bán cấu trúc. Bằng kỹ thuật dynamic shredding, các truy vấn trên nền tảng quan sát (observability) này có thể nhanh hơn tới 1.000 lần, biến những truy vấn từng mất 30 giây hoặc timeout thành phản hồi gần như tức thì.
Điểm đáng chú ý là người dùng không cần làm gì cả. Tính năng này sẽ được triển khai dần cho toàn bộ khách hàng từ tháng 2/2026.
Vấn đề: dữ liệu bán cấu trúc rất khó truy vấn nhanh
Logfire tiếp nhận dữ liệu theo chuẩn OpenTelemetry — vốn là dữ liệu bán cấu trúc, trộn lẫn giữa hai loại trường:
- Trường lược đồ cố định (timestamp, tên span, trace_id...) có kiểu dữ liệu chặt chẽ.
- Thuộc tính bán cấu trúc (mã trạng thái HTTP, user_id, region...) gửi qua các cặp key-value.
Ban đầu, Pydantic lưu toàn bộ thuộc tính dưới dạng một khối JSON duy nhất trong một cột, rồi dùng Jiter — một trong những bộ phân tích JSON nhanh nhất hiện nay — để xử lý. Cách này đơn giản nhưng mắc một sai lầm cơ bản: tối ưu để làm việc nhanh hơn, chứ không tránh được việc phải làm.
Khi dữ liệu lưu trên object storage, chi phí lớn nhất lại nằm ở I/O: tải về những khối JSON lớn và độ trễ khi bắt đầu tải thường chiếm phần lớn thời gian truy vấn, hơn cả thời gian CPU. Nén dữ liệu cũng kém hiệu quả vì chỉ một thuộc tính biến thiên cũng đủ vô hiệu hóa nén theo từ điển của Parquet.
Giải pháp ban đầu: static shredding và những giới hạn
Cách xử lý đầu tiên của Logfire là static shredding — chọn thủ công một số thuộc tính hay được truy vấn (như http.status_code, http.method) và tách chúng thành các cột riêng có kiểu chặt chẽ trong lúc ghi dữ liệu. Nhờ đó, truy vấn có thể dùng thống kê min-max để bỏ qua cả file hoặc nhóm hàng không liên quan.
Tuy nhiên, cách này bộc lộ nhiều hạn chế:
- Thiếu linh hoạt: chỉ một tập nhỏ thuộc tính được cố định sẵn. Muốn thêm thuộc tính mới phải sửa code và triển khai lại.
- Chi phí cao với thuộc tính chưa được tách: truy vấn trên
user_idhaysession_idvẫn phải quét toàn bộ cột JSON. - Cột lộ ra ngoài cho người dùng: các cột nội bộ như
_lf_attributes_http.response.status_codexuất hiện trong kết quả truy vấn, gây rối và khó hiểu. - Lãng phí tài nguyên: nhiều cột có thể toàn giá trị null nhưng vẫn tốn dung lượng và chi phí xử lý.
Một thuộc tính lớn hiếm gặp cũng đủ làm phình toàn bộ cột, khiến mọi truy vấn trở nên đắt đỏ — kể cả khi chúng không hề đụng tới thuộc tính đó.
Dynamic shredding: tự động tách cột theo thực tế dữ liệu
Thay vì lưu mọi thuộc tính trong một cột JSON, Logfire giờ tự động trích xuất những thuộc tính được truy cập nhiều nhất thành các cột riêng có kiểu chặt chẽ, ngay trong quá trình ghi dữ liệu và nén gộp — không cần cấu hình gì.
Cách bố trí vật lý được sinh động cho từng file Parquet dựa trên dữ liệu thực tế, nên không cần chứa các cột toàn null và có thể ưu tiên những thuộc tính lớn hoặc xuất hiện thường xuyên.
Kết quả là một truy vấn như tìm kiếm từ khóa trong phản hồi LLM:
SELECT * FROM events WHERE attributes->>'my_llm_response' LIKE '%important%';
trước đây phải tải và phân tích hàng GB JSON, nay chỉ cần quét đúng cột _lf_attributes_my_llm_response. Bốn lợi ích cộng dồn:
- Cắt tỉa bằng chỉ mục — zone map và chỉ mục tìm kiếm toàn văn giúp bỏ qua cả file hoặc nhóm hàng.
- Chỉ tải cột liên quan — giảm mạnh I/O và độ trễ.
- Nén tốt hơn — văn bản tiếng Anh nén hiệu quả hơn nhiều so với JSON hỗn hợp.
- Không còn phân tích JSON — dữ liệu đã được trích xuất và định kiểu sẵn, đọc vào bộ nhớ theo kiểu zero-copy.
Con đường gập ghềnh phía sau
Đội ngũ Pydantic đã dành gần 6 tháng cho tính năng này, phần lớn là để đóng góp thay đổi lên DataFusion — đẩy biểu thức và vị từ (predicate pushdown) xuống tận tầng đọc Parquet.
Đây là "con dao hai lưỡi" khi làm việc với dự án mã nguồn mở thượng nguồn: được xây trên nền tảng vững chắc, nhưng phải chờ thay đổi được chấp nhận và phát hành. Công việc cốt lõi đã hoàn tất trong DataFusion 52.1.0 (tháng 1/2026), phần còn lại dự kiến hoàn thành vào tháng 2/2026.
Điểm hay là những cải tiến này không chỉ phục vụ Logfire, mà còn giúp ích cho toàn bộ cộng đồng dùng DataFusion với dữ liệu bán cấu trúc và lồng nhau.
Quyết định tách thuộc tính nào như thế nào?
Phân tích dữ liệu sản xuất cho thấy 99% file Parquet hiện có ít hơn 128 khóa cấp cao nhất trong cột thuộc tính JSON, với trung vị (P50) chỉ khoảng 32 khóa. Vì vậy, mặc định hệ thống trích xuất 128 khóa lớn nhất (theo tổng kích thước qua mọi hàng).
Cơ chế này cân bằng giữa việc trích xuất đủ thuộc tính để phủ các mẫu truy vấn phổ biến và tránh phình lược đồ. Nó cũng chống chịu tốt với các trường hợp bệnh lý — chẳng hạn vô tình sinh ra 1.000 khóa ngẫu nhiên từ uuid.uuid4(): thuật toán sẽ tách các khóa phổ biến chiếm ưu thế và đẩy phần còn lại vào cột JSON rút gọn.
Về kiểu dữ liệu, hệ thống theo dõi kiểu dự kiến cho mỗi thuộc tính và mở rộng dần khi cần: Int -> Float -> JSON, Bool -> JSON, String -> JSON. Có sự khác biệt quan trọng giữa String và JSON:
[{"user_id": "123"}, {"user_id": 456}]→ lưu dạng JSON, vẫn cần phân tích nhưng hưởng lợi từ lưu trữ dạng cột và nén.["123", "456"]→ lưu thẳng dạng Utf8View, không cần phân tích JSON.
Hướng phát triển tiếp theo
Trong tương lai, đội ngũ Logfire dự định:
- Dùng kiểu Parquet Variant cho phần thuộc tính chưa được tách, hướng tới chuẩn công nghiệp mà các engine khác cũng đọc ghi được.
- Chỉ mục động — chỉ mục nghịch đảo cho tìm kiếm toàn văn, Bloom filter cho các cột có số lượng giá trị lớn.
- Tách cột dựa trên tần suất truy vấn — ví dụ
user_idtuy nhỏ nhưng được truy vấn liên tục thì vẫn đáng tách riêng.
Ý nghĩa với người dùng Việt Nam
Với các đội phát triển phần mềm trong nước đang dùng Logfire hoặc các hệ thống observability dựa trên OpenTelemetry, đây là tín hiệu đáng mừng: chi phí lưu trữ và tốc độ truy vấn log luôn là bài toán đau đầu, nhất là với ứng dụng dùng LLM và AI tạo sinh — nơi các thuộc tính như phản hồi mô hình có thể rất lớn nhưng lại chỉ xuất hiện ở một phần nhỏ các span.
Bạn không cần làm gì cả — chỉ cần tiếp tục dùng Logfire như hiện tại, và chờ các truy vấn của mình nhanh hơn vài bậc độ lớn trong vài tháng tới.
Bài viết liên quan

Công nghệ
BraiNOTES: Ghi chú viết tay trên PDF bài giảng ngay trong trình duyệt, không cần tài khoản
11 tháng 10, 2026

Công nghệ
Pensieve: Tìm kiếm cục bộ giúp giảm lệnh gọi công cụ và tiết kiệm token cho AI lập trình
12 tháng 10, 2026

Phần mềm
JulianFlux: Hạ tầng suy luận điện động lực học cho AI Agent
11 tháng 10, 2026