Tìm hiểu cách cơ sở dữ liệu theo cột lưu dữ liệu theo cột, nén và quét hiệu quả, và tăng tốc các truy vấn BI. So sánh với lưu trữ theo hàng và chọn giải pháp phù hợp.

Các truy vấn phân tích và báo cáo cung cấp dữ liệu cho dashboard BI, email KPI hàng tuần, các buổi “quý vừa rồi thế nào?”, và các câu hỏi ad‑hoc như “kênh marketing nào mang lại giá trị trọn đời cao nhất ở Đức?”. Chúng thường là các truy vấn đọc nhiều và tập trung vào tóm tắt lượng lớn dữ liệu lịch sử.
Thay vì lấy một bản ghi khách hàng duy nhất, truy vấn phân tích thường:
Hai điều làm phân tích khó khăn đối với engine cơ sở dữ liệu truyền thống:
Các hệ thống theo cột hướng tới làm cho phép quét và tổng hợp nhanh và dự đoán được — thường với chi phí trên truy vấn thấp hơn — đồng thời hỗ trợ độ đồng thời cao cho dashboard.
Tính tươi mới là một chiều riêng. Nhiều thiết lập phân tích đánh đổi cập nhật tức thời để có báo cáo nhanh hơn bằng cách nạp dữ liệu theo lô (mỗi vài phút hoặc hàng giờ). Một số nền tảng hỗ trợ ingest gần thời gian thực, nhưng cập nhật và xóa vẫn phức tạp hơn so với hệ thống giao dịch.
Cơ sở dữ liệu theo cột được xây chủ yếu cho công việc kiểu OLAP.
Cách đơn giản nhất để hiểu cơ sở dữ liệu theo cột là tưởng tượng cách một bảng được bố trí trên đĩa.
Hãy tưởng tượng một bảng orders:
| order_id | customer_id | order_date | status | total |
|---|---|---|---|---|
| 1001 | 77 | 2025-01-03 | shipped | 120.50 |
| 1002 | 12 | 2025-01-03 | pending | 35.00 |
| 1003 | 77 | 2025-01-04 | shipped | 89.99 |
Trong row store, cơ sở dữ liệu giữ các giá trị của cùng một hàng nằm cạnh nhau. Về khái niệm giống như:
Điều này hoàn hảo khi ứng dụng của bạn thường cần cả bản ghi (ví dụ “lấy order 1002 và cập nhật trạng thái”).
Trong column store, các giá trị cùng một cột được lưu gần nhau:
order_id: 1001, 1002, 1003, …status: shipped, pending, shipped, …total: 120.50, 35.00, 89.99, …Truy vấn phân tích thường chạm vài cột nhưng quét nhiều hàng. Ví dụ:
SUM(total) theo ngàyAVG(total) theo khách hàngGROUP BY status để đếm đơn hàngVới lưu trữ theo cột, một truy vấn như “doanh thu theo ngày” chỉ đọc order_date và total, thay vì kéo customer_id và status qua bộ nhớ cho mỗi hàng. Đọc ít dữ liệu hơn nghĩa là quét nhanh hơn — và đó là lợi thế cốt lõi của column store.
Lưu trữ theo cột nhanh cho phân tích vì hầu hết báo cáo không cần hầu hết dữ liệu. Nếu truy vấn chỉ dùng vài trường, cơ sở dữ liệu theo cột chỉ đọc những cột đó từ đĩa — thay vì kéo nguyên hàng.
Quét dữ liệu thường bị giới hạn bởi tốc độ chuyển byte từ lưu trữ vào bộ nhớ (rồi qua CPU). Row store thường đọc toàn bộ hàng, nghĩa là bạn nạp nhiều giá trị “thừa” mà bạn không cần.
Với columnar storage, mỗi cột nằm trong vùng liên tiếp. Vì vậy truy vấn như “doanh thu theo ngày” chỉ đọc:
Các trường khác (tên, địa chỉ, ghi chú, hàng chục thuộc tính hiếm dùng) ở lại trên đĩa.
Bảng phân tích có xu hướng trở nên rộng theo thời gian: thuộc tính sản phẩm mới, tag marketing, flags vận hành, và các trường “phòng khi cần”. Tuy nhiên báo cáo thường chạm một tập nhỏ — thường 5–20 cột trong hơn 100.
Lưu trữ theo cột phù hợp với thực tế đó. Nó tránh kéo theo các cột không dùng khiến việc quét bảng rộng trở nên tốn kém.
“Column pruning” nghĩa là cơ sở dữ liệu bỏ qua các cột truy vấn không tham chiếu. Điều đó giảm:
Kết quả là quét nhanh hơn, đặc biệt với tập dữ liệu lớn nơi chi phí đọc dữ liệu không cần thiết chiếm đa số thời gian truy vấn.
Nén là một “sức mạnh thầm lặng” của cơ sở dữ liệu theo cột. Khi dữ liệu được lưu theo cột, mỗi cột thường chứa cùng loại giá trị (ngày với ngày, quốc gia với quốc gia, mã trạng thái với mã trạng thái). Các giá trị giống nhau dễ nén hơn nhiều so với khi nhiều trường không liên quan đứng cạnh nhau trong row store.
Hãy nghĩ về cột order_status chủ yếu chứa "shipped", "processing" hoặc "returned" lặp đi lặp lại hàng triệu lần. Hoặc cột timestamp có giá trị tăng dần. Trong column store, các mẫu lặp hay có thể dự đoán được được gom cùng nhau, nên cơ sở dữ liệu có thể biểu diễn chúng bằng ít bit hơn.
Các engine phân tích thường kết hợp nhiều kỹ thuật, ví dụ:
Dữ liệu nhỏ hơn nghĩa là ít byte kéo từ đĩa hoặc object storage, và ít dữ liệu truyền qua bộ nhớ và cache CPU. Với các truy vấn báo cáo quét nhiều hàng nhưng chỉ vài cột, nén có thể giảm I/O đáng kể — thường phần chậm nhất của phân tích.
Một lợi ích thêm: nhiều hệ thống có thể thao tác trực tiếp trên dữ liệu nén hoặc giải nén theo lô lớn, giữ throughput cao khi thực hiện các phép tổng hợp như sum, count, group-by.
Nén không miễn phí. Cơ sở dữ liệu tiêu tốn CPU để nén dữ liệu khi ingest và giải nén khi thi hành truy vấn. Trong thực tế, các workload phân tích thường vẫn có lợi vì tiết kiệm I/O lớn hơn chi phí CPU — nhưng với truy vấn quá phụ thuộc vào CPU hoặc dữ liệu rất tươi, cân bằng có thể nghiêng ngược lại.
Lưu trữ theo cột giúp bạn đọc ít byte hơn. Xử lý vector giúp bạn tính toán nhanh hơn khi các byte đã vào bộ nhớ.
Engine truyền thống thường đánh giá truy vấn từng hàng một: tải một hàng, kiểm tra điều kiện, cập nhật tổng hợp, chuyển sang hàng tiếp theo. Cách này tạo nhiều phép toán nhỏ và nhiều nhánh, khiến CPU bận xử lý overhead thay vì công việc chính.
Vectorized execution đảo mô hình: engine xử lý giá trị theo lô (thường hàng nghìn giá trị của một cột cùng lúc). Thay vì gọi cùng một logic cho mỗi hàng, engine chạy vòng lặp tối ưu trên mảng giá trị.
Xử lý theo lô cải thiện hiệu quả CPU vì:
Giả sử: “Tổng doanh thu từ các đơn năm 2025 cho category = 'Books'.”
Một engine vectorized có thể:
category và tạo mask boolean nơi category bằng “Books”.order_date tương ứng và mở rộng mask để giữ chỉ 2025.revenue khớp và cộng chúng theo mask — thường dùng SIMD để cộng nhiều số mỗi chu kỳ CPU.Vì thao tác trên cột và lô, engine tránh chạm các trường không liên quan và tránh overhead theo hàng, lý do lớn khiến hệ thống theo cột vượt trội cho workload phân tích.
Truy vấn phân tích thường chạm nhiều hàng: “hiển thị doanh thu theo tháng”, “đếm sự kiện theo quốc gia”, “tìm top 100 sản phẩm”. Trong hệ thống OLTP, index là công cụ chính vì truy vấn thường lấy ít hàng theo khóa chính. Với phân tích, tạo và duy trì nhiều index tốn kém, và nhiều truy vấn vẫn cần quét lớn — nên column store tập trung làm cho phép quét thông minh và nhanh.
Nhiều hệ quản trị theo cột theo dõi metadata đơn giản cho mỗi block dữ liệu (gọi là “stripe”, “row group” hoặc “segment”), như giá trị tối thiểu và tối đa trong block.
Nếu truy vấn lọc amount > 100, và metadata của block nói max(amount) = 80, engine có thể bỏ qua toàn bộ block đó cho cột amount — mà không cần index truyền thống. Những “zone maps” này rẻ để lưu, nhanh để kiểm tra, và đặc biệt hiệu quả với cột có trật tự tự nhiên.
Phân vùng chia bảng thành các phần riêng biệt, thường theo ngày. Giả sử events phân vùng theo ngày và báo cáo hỏi WHERE event_date BETWEEN '2025-10-01' AND '2025-10-31'. Cơ sở dữ liệu có thể bỏ qua mọi phân vùng ngoài tháng 10 và chỉ quét phân vùng liên quan.
Điều này giảm I/O đáng kể vì bạn không chỉ bỏ qua block — bạn bỏ qua file hoặc phần vật lý lớn của bảng.
Nếu dữ liệu được sắp xếp (hoặc “clustered”) theo khóa lọc thường dùng — như event_date, customer_id, hoặc country — thì các giá trị khớp thường nằm cạnh nhau. Điều đó cải thiện cả hiệu quả partition pruning và zone-map, vì các block không liên quan nhanh chóng thất bại kiểm tra min/max và bị bỏ qua.
Cơ sở dữ liệu theo cột nhanh không chỉ vì đọc ít dữ liệu mỗi truy vấn, mà còn vì có thể đọc nó song song.
Một truy vấn phân tích (ví dụ “tổng doanh thu theo tháng”) thường cần quét hàng triệu hoặc hàng tỷ giá trị. Column store thường chia công việc cho các lõi CPU: mỗi lõi quét một chunk khác nhau của cùng một cột (hoặc tập phân vùng khác nhau). Thay vì một hàng dài ở quầy, bạn mở nhiều quầy cùng lúc.
Vì dữ liệu cột được lưu trong các block lớn, liên tiếp, mỗi lõi có thể stream qua block của nó hiệu quả — tận dụng cache CPU và băng thông đĩa.
Khi dữ liệu quá lớn cho một máy, cơ sở dữ liệu có thể phân tán nó qua nhiều server. Truy vấn được gửi đến mọi node chứa chunk liên quan, và mỗi node thực hiện quét cục bộ và tính toán một phần.
Ở đây vị trí dữ liệu quan trọng: thường nhanh hơn khi “di chuyển tính toán tới dữ liệu” hơn là gửi raw rows qua mạng. Mạng chậm hơn bộ nhớ và có thể trở thành nút cổ chai nếu truy vấn cần chuyển nhiều kết quả trung gian.
Nhiều phép tổng hợp có tính chất song song:
Dashboard có thể kích hoạt nhiều truy vấn tương tự cùng lúc — đặc biệt vào đầu giờ hoặc trong các cuộc họp. Column store thường kết hợp song song với lập lịch thông minh (và đôi khi cache kết quả) để giữ độ trễ ổn định khi hàng chục hoặc hàng trăm người dùng làm mới biểu đồ đồng thời.
Cơ sở dữ liệu theo cột mạnh khi bạn đọc nhiều hàng nhưng chỉ vài cột. Đổi lại, chúng thường kém phù hợp với workload thay đổi liên tục từng hàng.
Trong row store, cập nhật một bản ghi khách hàng thường ghi lại một mảnh dữ liệu nhỏ, liên tiếp. Trong column store, “một hàng” trải ra nhiều tệp/segment cột. Cập nhật có thể yêu cầu chạm nhiều nơi, và vì column store dựa vào nén và block đóng gói chặt, thay đổi tại chỗ có thể buộc phải ghi lại các chunk lớn hơn bạn nghĩ.
Hầu hết column store phân tích dùng cách hai giai đoạn:
Đó là lý do bạn thường thấy các thuật ngữ như “delta + main”, “ingestion buffer”, “compaction”, hoặc “merge”.
Nếu bạn cần dashboard phản ánh thay đổi tức thì, một column store thuần túy có thể cảm thấy trễ hoặc tốn kém. Nhiều nhóm chấp nhận gần thời gian thực (ví dụ 1–5 phút) để các merge có thể diễn ra hiệu quả và truy vấn vẫn nhanh.
Cập nhật/xóa thường tạo “tombstone” (dấu hiệu xóa/phiên bản cũ) và segment bị phân mảnh. Điều đó tăng lưu trữ và làm chậm truy vấn cho đến khi tiến trình bảo trì (vacuum/compaction) dọn dẹp. Lên kế hoạch cho việc bảo trì — thời điểm, giới hạn tài nguyên, và quy tắc giữ — là phần quan trọng để giữ hiệu năng báo cáo ổn định.
Mô hình tốt quan trọng như engine. Lưu trữ theo cột có thể quét và tổng hợp nhanh, nhưng cách bạn cấu trúc bảng quyết định bao nhiêu lần cơ sở dữ liệu có thể tránh cột không cần thiết, bỏ qua phần dữ liệu, và chạy GROUP BY hiệu quả.
Star schema tổ chức dữ liệu thành một bảng fact trung tâm bao quanh bởi các bảng dimension nhỏ hơn. Nó phù hợp vì hầu hết báo cáo:
Columnar systems hưởng lợi vì truy vấn thường chạm một tập nhỏ cột trong bảng fact rộng.
Ví dụ:
fact_orders: order_id, order_date_id, customer_id, product_id, quantity, net_revenuedim_customer: customer_id, region, segmentdim_product: product_id, category, branddim_date: date_id, month, quarter, yearMột báo cáo như “net revenue theo tháng và vùng” tổng hợp net_revenue từ fact_orders và nhóm theo thuộc tính từ dim_date và dim_customer.
Star schema dựa vào join. Nhiều cơ sở dữ liệu theo cột xử lý join tốt, nhưng chi phí join vẫn tăng theo kích thước dữ liệu và độ đồng thời truy vấn.
Denormalization có thể giúp khi một thuộc tính dimension dùng liên tục (ví dụ copy region vào fact_orders). Đổi lại là hàng fact lớn hơn, giá trị lặp lại nhiều hơn, và công việc thêm khi thuộc tính thay đổi. Thường thì compromise là giữ dimension chuẩn nhưng cache các thuộc tính “hot” trong fact chỉ khi nó thực sự cải thiện dashboard chính.
region, category) và giữ chúng độ phân giải thấp tới trung bình khi có thể.date_id, rồi customer_id) để làm cho bộ lọc và GROUP BY rẻ hơn.Cơ sở dữ liệu theo cột thường thắng khi câu hỏi chạm nhiều hàng nhưng chỉ một tập cột — đặc biệt khi kết quả là tổng hợp (sum, average, percentiles) hoặc báo cáo nhóm (theo ngày, theo vùng, theo phân khúc khách hàng).
Số liệu time-series: CPU, độ trễ app, sensor IoT và các dữ liệu “một hàng cho mỗi khoảng thời gian” đều phù hợp. Truy vấn thường quét khoảng thời gian và tính rollup như trung bình theo giờ hoặc xu hướng hàng tuần.
Event logs và clickstream: (view, search, purchase) cũng phù hợp. Các nhà phân tích thường lọc theo ngày, chiến dịch, hoặc phân khúc người dùng, rồi tổng hợp lượt, funnel và tỉ lệ chuyển đổi trên hàng triệu đến hàng tỷ sự kiện.
Tài chính và báo cáo kinh doanh: lợi ích hàng tháng theo dòng sản phẩm, cohort retention, ngân sách so với thực tế, và các báo cáo nhóm/tổng khác. Columnar giữ quét hiệu quả kể cả khi bảng rộng.
Nếu workload của bạn chủ yếu là tra cứu điểm cao tốc (lấy một người dùng theo ID) hoặc cập nhật giao dịch nhỏ (cập nhật trạng thái đơn nhiều lần mỗi phút), cơ sở dữ liệu OLTP theo hàng thường phù hợp hơn.
Column store có thể hỗ trợ insert và một số update, nhưng thay đổi hàng thường xuyên có thể chậm hoặc phức tạp vận hành (ví dụ write amplification, merge, hoặc hiển thị trì hoãn tùy hệ thống).
Trước khi quyết định, benchmark với:
Một PoC nhanh dùng dữ liệu hình dạng sản xuất sẽ cho bạn câu trả lời nhiều hơn các test tổng hợp hay so sánh nhà cung cấp.
Chọn một column-oriented database không chỉ dựa vào benchmark mà là kết hợp hệ thống với thực tế báo cáo của bạn: ai truy vấn, bao lâu, và câu hỏi có định hình không.
Tập trung vào vài chỉ số quyết định:
Một danh sách ngắn các câu trả lời sẽ thu hẹp lựa chọn nhanh:
Hầu hết nhóm không query DB trực tiếp. Xác nhận tương thích với:
Giữ nhỏ nhưng thực tế:
Nếu ứng viên thắng trên các chỉ số đó và phù hợp mức độ vận hành của bạn, thường là lựa chọn đúng.
Hệ thống theo cột cảm thấy nhanh cho phân tích vì chúng tránh công việc bạn không cần. Chúng đọc ít byte hơn (chỉ các cột tham chiếu), nén chúng rất hiệu quả (ít traffic đĩa và bộ nhớ hơn), và thực thi theo lô thân thiện với cache CPU. Thêm song song trên lõi và node, các truy vấn báo cáo từng chậm có thể xong trong vài giây.
Sử dụng checklist nhẹ này trước hoặc trong khi áp dụng:
Theo dõi vài tín hiệu đều đặn:
Nếu các quét quá lớn, xem lại lựa chọn cột, phân vùng và thứ tự trước khi thêm phần cứng.
Bắt đầu chuyển các workload “chủ yếu đọc”: báo cáo hàng đêm, dashboard BI và khám phá ad-hoc. Sao chép dữ liệu từ hệ giao dịch vào column store, kiểm tra kết quả song song, rồi chuyển người dùng từng nhóm. Giữ phương án rollback (chạy đôi trong một cửa sổ ngắn) và chỉ mở rộng khi monitoring cho thấy khối lượng quét ổn định và hiệu năng dự đoán được.
Column store cải thiện hiệu năng truy vấn, nhưng các đội thường tốn thời gian xây dựng phần trải nghiệm xung quanh: portal chỉ số nội bộ, kiểm soát theo vai trò, giao hàng báo cáo theo lịch, và các công cụ phân tích “một lần” sau thành tính năng cố định.
Nếu bạn muốn nhanh hơn ở lớp ứng dụng đó, Koder.ai giúp sinh ứng dụng web (React), dịch vụ backend (Go) và tích hợp PostgreSQL từ flow lập kế hoạch dạng chat. Thực tế, điều này hữu ích để nhanh chóng thử nghiệm:
Vì Koder.ai hỗ trợ xuất mã nguồn, deployment/hosting và snapshot với rollback, bạn có thể lặp nhanh các tính năng báo cáo đồng thời giữ kiểm soát thay đổi — hữu ích khi nhiều bên liên quan phụ thuộc vào cùng dashboard.
Analytics và truy vấn báo cáo là các câu hỏi chú trọng đọc dữ liệu, tóm tắt nhiều dữ liệu lịch sử — như doanh thu theo tháng, chuyển đổi theo chiến dịch, hoặc giữ chân theo cohort. Chúng thường quét nhiều hàng, chạm một tập con cột, tính toán các tổng hợp và trả về một tập kết quả nhỏ cho biểu đồ hoặc bảng.
Chúng gây áp lực lên cơ sở dữ liệu chủ yếu vì:
Các engine OLTP theo hàng có thể xử lý, nhưng chi phí và độ trễ thường trở nên khó dự đoán ở quy mô lớn.
Trong row store, các giá trị của cùng một hàng nằm cạnh nhau trên đĩa, rất phù hợp để lấy hoặc cập nhật một bản ghi. Trong column store, các giá trị của cùng một cột nằm cạnh nhau, rất phù hợp khi truy vấn đọc một vài cột trên nhiều hàng.
Nếu báo cáo chỉ cần order_date và total, column store có thể tránh đọc các cột không liên quan như status hoặc customer_id.
Vì hầu hết truy vấn phân tích chỉ đọc một tập nhỏ cột. Column store thực hiện column pruning (bỏ qua các cột không dùng), nên đọc ít byte hơn.
Đọc ít I/O hơn thường nghĩa là:
Bố cục theo cột gom các giá trị giống nhau lại với nhau (ngày với ngày, quốc gia với quốc gia), nên nén rất hiệu quả.
Các phương pháp phổ biến:
Nén giảm lưu trữ và tăng tốc quét bằng cách cắt bớt I/O, dù có chi phí CPU để nén/giải nén.
Thực thi vector (vectorized execution) xử lý dữ liệu theo lô (mảng giá trị) thay vì theo hàng.
Lợi ích:
Đây là lý do chính khiến column store vẫn nhanh dù phải quét phạm vi lớn.
Nhiều engine lưu metadata nhẹ cho mỗi khối dữ liệu (ví dụ min/max). Nếu bộ lọc truy vấn không thể khớp một khối (ví dụ max(amount) < 100 cho amount > 100), engine có thể bỏ qua toàn bộ khối đó.
Kết hợp với:
sẽ giúp giảm đáng kể I/O.
Song song biểu hiện ở hai dạng:
Mô hình “chia‑và‑gộp” này giúp group-by và các phép tổng hợp mở rộng tốt mà không phải truyền thô nhiều hàng trên mạng.
Cập nhật một hàng đơn khó hơn vì một “hàng” vật lý bị trải ra nhiều tệp/segment cột, thường được nén. Thay đổi một giá trị có thể buộc phải ghi lại các khối cột lớn hơn.
Các chiến lược phổ biến:
Vì vậy nhiều hệ thống chấp nhận độ trễ gần thời gian thực (ví dụ 1–5 phút) thay vì cập nhật tức thì.
Dùng dữ liệu thực tế và các truy vấn thật để benchmark:
Một PoC nhỏ với 10–20 truy vấn thực tế thường cho nhiều thông tin hơn các benchmark nhà cung cấp.