Cài đặt DuckDB CLI và Python Package trên Ubuntu 24.04
Chúng ta sẽ bắt đầu bằng việc cài đặt DuckDB CLI (Command Line Interface) để thao tác trực tiếp trên shell và Python package để tích hợp vào pipeline ETL.
Đầu tiên, thêm repository chính thức của DuckDB vào hệ thống Ubuntu 24.04 để đảm bảo luôn nhận được bản cập nhật mới nhất.
curl -fsSL https://raw.githubusercontent.com/duckdb/duckdb/master/scripts/install.sh | bash
Command trên sẽ tải script cài đặt từ GitHub, tự động thêm key GPG và repository vào nguồn apt, sau đó cài đặt gói duckdb.
Kết quả mong đợi: Bạn thấy thông báo "DuckDB is now installed" và không có lỗi về repository hay key signing.
Tiếp theo, cài đặt gói Python. Chúng ta sẽ sử dụng pip từ Python 3 mặc định có sẵn trên Ubuntu 24.04.
python3 -m pip install --upgrade pip duckdb
Việc này cài đặt thư viện duckdb cho Python, cho phép bạn import module `duckdb` trong script Python và thực thi SQL.
Kết quả mong đợi: Pip hiển thị thông báo "Successfully installed duckdb-..." kèm theo phiên bản.
Để verify, kiểm tra phiên bản của cả CLI và Python package.
duckdb --version
python3 -c "import duckdb; print(duckdb.__version__)"
Cả hai command phải trả về cùng một phiên bản số (ví dụ: 1.0.0) để đảm bảo tính tương thích.
Thiết lập Cơ sở dữ liệu In-Process và Kiến trúc
DuckDB hoạt động theo kiến trúc in-process (xử lý trong tiến trình), nghĩa là không có server database riêng biệt chạy lắng nghe port. Database file được mở và đóng trực tiếp bởi ứng dụng.
Tạo thư mục làm việc để chứa các file database và dữ liệu mẫu.
mkdir -p ~/duckdb-workspace && cd ~/duckdb-workspace
Kết quả mong đợi: Bạn đã chuyển vào thư mục mới, shell prompt hiện đường dẫn ~/duckdb-workspace.
Khởi tạo file database vật lý đầu tiên. Dù DuckDB hỗ trợ chế độ in-memory (không lưu vào disk), việc tạo file .db giúp dữ liệu tồn tại sau khi tắt session.
duckdb -c "CREATE DATABASE 'analytics.db';" ~/duckdb-workspace/analytics.db
Command này tạo file `analytics.db` và thực thi câu lệnh SQL tạo database bên trong file đó. Lưu ý DuckDB cho phép nhiều database trong một file, nhưng thông lệ là 1 file = 1 database.
Kết quả mong đợi: Không có output lỗi, và file `analytics.db` xuất hiện trong thư mục hiện tại.
Khởi động CLI DuckDB và kết nối vào database vừa tạo để thực hiện các thao tác.
duckdb ~/duckdb-workspace/analytics.db
Trong CLI, bạn sẽ thấy prompt thay đổi từ shell sang `duckdb>`, biểu thị bạn đang ở trong môi trường SQL của DuckDB.
Kiểm tra xem database đã kết nối chưa bằng câu lệnh SQL.
SELECT current_database();
Kết quả mong đợi: Một bảng hiển thị tên `current_database` với giá trị là `analytics`.
Chạy SQL Cơ bản và Import Dữ liệu Mẫu (CSV, JSON)
DuckDB có khả năng đọc trực tiếp các file định dạng phổ biến như CSV và JSON mà không cần bước import chuyển đổi (ETL) phức tạp trước đó.
Đầu tiên, tạo một file CSV mẫu chứa dữ liệu giao dịch để làm việc.
cat > transactions.csv
Command này sử dụng heredoc để tạo file `transactions.csv` ngay trong thư mục hiện tại với 5 dòng dữ liệu mẫu.
Kết quả mong đợi: File `transactions.csv` được tạo thành công.
Tạo bảng trong DuckDB và nạp dữ liệu trực tiếp từ file CSV. DuckDB tự động suy luận schema (kiểu dữ liệu) từ file.
CREATE TABLE transactions AS SELECT * FROM read_csv_auto('transactions.csv');
Hàm `read_csv_auto()` sẽ đọc file, phát hiện delimiter, và ánh xạ các cột sang kiểu dữ liệu phù hợp (INTEGER, DOUBLE, DATE).
Kết quả mong đợi: Thông báo "5 rows inserted" hoặc tương tự.
Thực hiện truy vấn SQL cơ bản để kiểm tra dữ liệu đã vào bảng chưa.
SELECT * FROM transactions WHERE amount > 100 ORDER BY amount DESC;
Query này lọc các giao dịch có số tiền lớn hơn 100 và sắp xếp giảm dần.
Kết quả mong đợi: Hiển thị 2 dòng dữ liệu (150.50 và 1200.00).
Bây giờ, xử lý dữ liệu JSON. Tạo file JSON mẫu chứa thông tin người dùng.
cat > users.json
File JSON này chứa một mảng các object. DuckDB có thể đọc mảng JSON và flatten thành bảng quan hệ.
Tạo bảng từ file JSON.
CREATE TABLE users AS SELECT * FROM read_json_auto('users.json');
Hàm `read_json_auto()` tự động xử lý cấu trúc JSON và chuyển đổi thành bảng SQL.
Kết quả mong đợi: Thông báo "3 rows inserted".
Thực hiện Join giữa hai bảng để chứng minh khả năng xử lý quan hệ.
SELECT u.name, t.amount FROM users u JOIN transactions t ON u.id = t.id;
Query này nối bảng `users` và `transactions` dựa trên khóa chính `id`.
Kết quả mong đợi: Hiển thị 3 dòng kết hợp tên người dùng và số tiền giao dịch tương ứng.
Thoát khỏi CLI DuckDB để chuẩn bị cho bước tối ưu hóa.
EXIT
Cấu hình Tối ưu Bộ nhớ và Hiệu năng Đọc/Ghi
Để tối ưu hiệu năng cho các workload lớn, chúng ta cần điều chỉnh các tham số memory và thread của DuckDB. Mặc định, DuckDB sử dụng 1/4 RAM hệ thống và số lượng CPU cores có sẵn.
Trong môi trường production hoặc serverless, việc kiểm soát chính xác bộ nhớ là cần thiết để tránh OOM (Out Of Memory).
Tạo file cấu hình DuckDB. DuckDB CLI không hỗ trợ file config `.ini` chuẩn như MySQL, nhưng ta có thể sử dụng biến môi trường hoặc set parameter trong session. Tuy nhiên, để lưu cấu hình mặc định cho CLI, ta sẽ dùng script khởi động.
Tạo file script khởi động với các tham số tối ưu tại `~/duckdb-workspace/start_duckdb.sh`.
cat > ~/duckdb-workspace/start_duckdb.sh
Script này thiết lập biến môi trường `DUCKDB_MEMORY_LIMIT` và `DUCKDB_THREADS` trước khi gọi lệnh `duckdb`. Đây là cách chuẩn để cấu hình hành vi runtime của DuckDB CLI.
Cấp quyền thực thi cho script.
chmod +x ~/duckdb-workspace/start_duckdb.sh
Kết quả mong đợi: Không có lỗi, file có quyền execute.
Chạy script để khởi động DuckDB với cấu hình mới.
~/duckdb-workspace/start_duckdb.sh
Khi prompt `duckdb>` xuất hiện, các tham số đã được áp dụng ngay từ khi khởi tạo engine.
Verify cấu hình bằng cách query các parameter hiện hành.
PRAGMA memory_limit;
PRAGMA threads;
Câu lệnh `PRAGMA` trả về giá trị hiện tại của các tham số cấu hình.
Kết quả mong đợi: `memory_limit` trả về giá trị xấp xỉ 2GB (thường hiển thị dưới dạng byte hoặc GB) và `threads` trả về số 4.
Tiếp tục tối ưu cho việc đọc/ghi bằng cách kích hoạt nén dữ liệu (Compression). Mặc định DuckDB sử dụng Snappy, nhưng ta có thể xác nhận hoặc thay đổi nếu cần.
Thử nghiệm tạo bảng với cấu hình nén cụ thể (ví dụ: ZSTD cho dữ liệu văn bản nén tốt hơn).
CREATE TABLE large_logs (id INT, message TEXT) WITH (compression='ZSTD');
Tham số `WITH (compression=...)` áp dụng cho từng bảng, giúp giảm dung lượng disk và tăng tốc độ I/O khi đọc các cột text lớn.
Kết quả mong đợi: Bảng `large_logs` được tạo thành công.
Để Python package cũng áp dụng cấu hình tương tự, ta cần set trong code Python. Tạo file script Python mẫu để test cấu hình từ Python.
cat > ~/duckdb-workspace/config_test.py
Script này minh họa cách thiết lập cấu hình động trong Python, rất hữu ích cho các ứng dụng serverless nơi môi trường thay đổi liên tục.
Chạy script Python để verify.
python3 ~/duckdb-workspace/config_test.py
Kết quả mong đợi: Output hiển thị Memory Limit và Threads đúng với giá trị đã set (2GB và 4).
Thoát khỏi CLI DuckDB nếu vẫn đang chạy.
EXIT
Điều hướng series:
Mục lục: Series: Xây dựng Data Lakehouse Serverless với DuckDB, Apache Iceberg và Ubuntu 24.04
« Phần 1: Khởi động: Chuẩn bị môi trường Ubuntu 24.04 và yêu cầu hệ thống
Phần 3: Nhập môn Apache Iceberg: Kiến trúc và cài đặt thư viện Python »