1. Giới thiệu DuckDB
- DuckDB là một cơ sở dữ liệu quan hệ dạng cột, tối ưu cho xử lý phân tích dữ liệu.
- Được thiết kế để chạy trên một máy đơn mà không cần server, giống SQLite.
- Hỗ trợ SQL chuẩn, tích hợp tốt với Python, R, và các công cụ phân tích dữ liệu khác.
- Tối ưu truy vấn nhanh: Nhờ vectorized execution.
- Hỗ trợ nhiều định dạng file như CSV, Parquet, ORC, JSON.
curl -L https://github.com/duckdb/duckdb/releases/latest/download/duckdb_cli-linux-amd64.zip -o duckdb.zipunzip duckdb.zipchmod +x duckdb./duckdb
2.2. Cài đặt trên Windows
Tải DuckDB từ trang chủ và giải nén để sử dụng.
3. Hướng dẫn sử dụng DuckDB
3.1. Kết nối với DuckDB
Tại vị trí của thư mục giải nén DuckDB, mở command line vào tạo cơ sở dữ liệu demo:
Kết nối đến cơ sở dữ liệu demo trong DuckDB, có thể dử dụng DBeaver
Nếu dữ liệu lớn (> 10M dòng), có thể dùng DuckDB với file Parquet, ORC để tăng tốc.
3.2. Làm việc với CSV, ORC và Parquet
3.2.1. Đọc CSV
CREATE TABLE users AS SELECT * FROM read_csv_auto('users.csv');
3.2.2. Đọc ORC
SELECT * FROM read_orc('data.orc');
3.2.3. Đọc Parquet
SELECT * FROM read_parquet('data.parquet');
4. Tối ưu cơ sở dữ liệu DuckDB
4.1. Sử dụng Parquet
DuckDB lưu trữ dữ liệu theo định dạng cột giúp tăng tốc truy vấn. Tuy nhiên, nếu thường xuyên thao tác với lượng dữ liệu lớn, hãy sử dụng Parquet thay vì CSV hoặc bảng nội bộ.
- Lưu dữ liệu dưới dạng Parquet: COPY users TO 'users.parquet' (FORMAT PARQUET);
- Đọc Parquet thay vì CSV: SELECT * FROM read_parquet('users.parquet');
- Truy vấn trực tiếp trên nhiều file Parquet mà không nhập vào DuckDB: SELECT * FROM read_parquet('s3://bigdata/sales/*.parquet') WHERE year=2024;
- Lợi ích:
- Nén dữ liệu tốt hơn, giảm kích thước file.
- Tương thích với nhiều hệ thống khác như Spark, Pandas, và SQL engines.
- DuckDB hỗ trợ ZSTD và Snappy để nén dữ liệu trong Parquet: COPY users TO 'users.parquet' (FORMAT PARQUET, COMPRESSION ZSTD);
- Lợi ích:
- Giảm kích thước file.
- Tăng tốc truy vấn do giảm I/O.
4.3. Sử dụng Adaptive Query Optimization (AQO)
- DuckDB có thể tối ưu hóa truy vấn tự động dựa trên dữ liệu thực tế. Kích hoạt bằng: PRAGMA enable_aqo;
4.4. Dùng Indexed Joins thay vì Hash Joins
DuckDB mặc định sử dụng hash joins, nhưng nếu bảng đã được sắp xếp theo khóa thì indexed joins sẽ hiệu quả hơn. Kích hoạt bằng: PRAGMA enable_indexed_join;
- Lợi ích:
- Giảm bộ nhớ sử dụng cho các phép JOIN.
- Tăng tốc độ khi JOIN trên khóa có thứ tự.
4.5. Tránh sử dụng quá nhiều NULL
DuckDB tối ưu hóa dữ liệu bằng cách sử dụng bitmaps để lưu trữ NULL. Nếu bảng có quá nhiều NULL, truy vấn có thể chậm hơn.
- Cách tránh NULL:
- Dùng giá trị mặc định thay thế NULL: SELECT COALESCE(age, 0) FROM users;
- Tạo cột boolean thay vì NULL: ALTER TABLE users ADD COLUMN is_active BOOLEAN DEFAULT TRUE;
- Lợi ích:
- Giảm bộ nhớ sử dụng.
- Truy vấn nhanh hơn do không cần kiểm tra NULL.
4.6. Tận dụng truy vấn song song
DuckDB hỗ trợ multithreading, có thể kích hoạt để tận dụng CPU đa lõi:
PRAGMA threads=128; -- Sử dụng 128 CPU threadsPRAGMA enable_profiling='json'; -- Bật profiling để phân tích hiệu suất
4.7. Sử dụng Temporary Tables để tăng tốc độ truy vấn phức tạp
Nếu cần chạy nhiều truy vấn phức tạp trên cùng một tập dữ liệu, hãy sử dụng bảng tạm (temporary tables) để tránh tránh đọc dữ liệu từ file gốc nhiều lần và tăng tốc độ xử lý do dữ liệu đã được lọc sẵn.
Tạo bảng tạm thời:
CREATE TEMP TABLE temp_users ASSELECT * FROM users WHERE age > 30;
4.8. Giảm bộ nhớ sử dụng bằng cách chỉ chọn cột cần thiết
DuckDB đọc dữ liệu theo từng cột, vì vậy tránh sử dụng SELECT * nếu không cần thiết giúp giảm I/O disk khi đọc dữ liệu và tăng tốc độ truy vấn trên dataset lớn.
SELECT name, age FROM users;
4.9. Dùng read_csv_auto() để đọc CSV nhanh hơn
Thay vì chỉ dùng read_csv(), hãy để DuckDB tự phát hiện kiểu dữ liệu bằng read_csv_auto() để read_csv_auto() tự động xác định kiểu dữ liệu chuẩn hơn và giảm lỗi khi đọc file CSV: SELECT * FROM read_csv_auto('sales.csv');
4.10. Tạo chỉ mục tạm thời để tăng tốc truy vấn
DuckDB không hỗ trợ chỉ mục truyền thống như PostgreSQL hay MySQL, nhưng có thể tối ưu truy vấn bằng cách tạo Materialized Views.
Tạo Materialized View:
CREATE MATERIALIZED VIEW fast_users ASSELECT * FROM users WHERE age > 30;
Sau đó, truy vấn trên fast_users sẽ nhanh hơn rất nhiều so với truy vấn toàn bộ bảng users.
4.11. Chia dữ liệu thành nhiều file nhỏ (Partitioning)
Nếu file dữ liệu rất lớn, hãy chia thành nhiều file nhỏ để tăng tốc truy vấn.
Ví dụ: Chia dữ liệu theo năm và tháng:
COPY (SELECT * FROM sales WHERE year=2023) TO 'sales_2023.parquet' (FORMAT PARQUET);COPY (SELECT * FROM sales WHERE year=2024) TO 'sales_2024.parquet' (FORMAT PARQUET);
Sau đó, truy vấn dữ liệu nhanh hơn bằng cách chọn đúng file cần dùng:
SELECT * FROM read_parquet('sales_2023.parquet') WHERE month = 'January';
4.12. Truy vấn dữ liệu lớn bằng cách quét file trực tiếp
Thay vì nhập dữ liệu vào bảng, DuckDB có thể truy vấn trực tiếp trên file (CSV, Parquet) giúp không tải dữ liệu vào RAM, giảm mức sử dụng bộ nhớ đáng kể.
SELECT COUNT(*) FROM read_parquet('sales.parquet');
4.13. Tăng tốc DuckDB với SSD NVMe và RAM đủ lớn
- DuckDB hoạt động tốt nhất trên SSD NVMe tốc độ cao.
- Cần RAM đủ lớn để giữ cache dữ liệu quan trọng.
4.14. Chạy DuckDB trên HPC hoặc dùng Server lớn
Nếu xử lý dữ liệu lớn hơn 10PB, dùng:
- Máy chủ HPC với RAM 1TB+ và CPU đa lõi (> 64 cores).
- Cấu hình DuckDB trên máy ảo với lưu trữ phân tán.
- Dùng DuckDB với S3 hoặc hệ thống lưu trữ đám mây (MinIO, HDFS).
SELECT * FROM read_parquet('s3://bucket/data.parquet');
- Dùng Kubernetes + DuckDB để tự động mở rộng xử lý Geopbyte dữ liệu:
- Sử dụng HPA (Horizontal Pod Autoscaler) để mở rộng Pod DuckDB dựa trên mức sử dụng CPU hoặc RAM.
- Bật Autoscale bằng lệnh Kubectl: kubectl autoscale deployment duckdb --cpu-percent=70 --min=3 --max=10. Tự động scale từ 3 đến 10 Pod dựa trên CPU.
- Kết hợp với Cluster Autoscaler (tăng máy ảo khi cần): Nếu cluster Kubernetes không đủ tài nguyên, ta cần Cluster Autoscaler để tăng số lượng node (server) khi DuckDB cần thêm tài nguyên.
Bật Cluster Autoscaler trên GKE (Google Kubernetes Engine):
gcloud container clusters update my-cluster --enable-autoscaling --min-nodes=3 --max-nodes=20
Bật Cluster Autoscaler trên AWS EKS:
eksctl create nodegroup --cluster=my-cluster --min=3 --max=20
- Scale-in khi dữ liệu giảm:
- HPA sẽ giảm số lượng Pod nếu CPU/RAM thấp hơn mức quy định.
- Nếu số Pod < minReplicas, Kubernetes không scale xuống nữa để đảm bảo DuckDB luôn chạy.
- Kiểm tra số lượng Pod sau khi autoscale: kubectl get hpa
4.15. Sử dụng DuckDB với Spark hoặc Polars để xử lý PB-Scale
DuckDB rất mạnh trên một máy đơn, nhưng với Petabyte dữ liệu, có thể kết hợp với Apache Spark hoặc Polars để phân tán xử lý:
import polars as plimport duckdbdf = pl.read_parquet("bigdata.parquet").lazy()duckdb.query("SELECT * FROM df WHERE year=2023")
4.16. Sử dụng lưu trữ phân tán (S3, MinIO, HDFS)
DuckDB hỗ trợ truy vấn trên S3, MinIO, HDFS mà không cần tải về.
INSTALL httpfs;LOAD httpfs;SELECT * FROM read_parquet('s3://bucket/data.parquet');