- Một giải pháp mới hợp nhất data lake và định dạng catalog
- Hoạt động dựa trên các tệp Parquet và cơ sở dữ liệu SQL, cho phép triển khai data lake gọn nhẹ hơn so với lakehouse truyền thống
- Có thể quản lý catalog metadata trên nhiều cơ sở dữ liệu như PostgreSQL, SQLite, MySQL, DuckDB
- Hỗ trợ nhiều tính năng như snapshot, truy vấn time travel, thay đổi schema, partitioning đồng thời cung cấp xử lý snapshot nhẹ mà không cần compact thường xuyên
- Hỗ trợ mô hình DuckDB nhiều người chơi trong đó nhiều instance có thể đồng thời đọc và ghi dữ liệu, hiện thực mô hình xử lý đồng thời mà DuckDB mặc định không hỗ trợ
- DuckLake là khái niệm bao trùm đặc tả, tiện ích mở rộng DuckDB và các dataset được lưu theo định dạng DuckLake, và được phát hành theo giấy phép MIT
Giới thiệu về DuckLake
- DuckLake là một định dạng mở do đội ngũ DuckDB tạo ra, cung cấp các tính năng data lake nâng cao mà không cần lakehouse phức tạp
- Chỉ cần cơ sở dữ liệu SQL và các tệp Parquet là có thể xây dựng kho dữ liệu riêng.
- Sử dụng cơ sở dữ liệu để quản lý metadata: PostgreSQL, SQLite, MySQL, DuckDB
Các tính năng chính của DuckLake
-
Vận hành data lake
- Snapshot
- Truy vấn theo thời điểm (Time travel)
- Tiến hóa schema
- Partitioning
-
Xử lý snapshot nhẹ
- Có thể tạo snapshot không giới hạn số lượng
- Có thể vận hành mà không cần compact thường xuyên
-
Giao dịch ACID
- Đảm bảo truy cập đồng thời và giao dịch cho các thao tác trên nhiều bảng
-
Thiết kế hướng hiệu năng
- Tận dụng thống kê cho filter pushdown
- Truy vấn nhanh ngay cả trên các dataset lớn
Câu hỏi thường gặp
-
Vì sao nên dùng DuckLake?
- Phù hợp khi cần một giải pháp nhẹ hợp nhất data lake và catalog
- Có thể xây dựng môi trường nhiều người chơi nơi nhiều instance DuckDB cùng đọc và ghi trên cùng một dataset
- Đây là mô hình đồng thời mà DuckDB hiện có không hỗ trợ
- Ngay cả khi chỉ dùng DuckDB, vẫn có thể hưởng lợi từ truy vấn theo thời điểm, partitioning và cấu trúc lưu trữ nhiều tệp
-
DuckLake là gì?
- DuckLake dùng để chỉ ba thành phần sau:
- Đặc tả của định dạng DuckLake (specification)
- Tiện ích mở rộng DuckDB hỗ trợ DuckLake (ducklake extension)
- Chính dataset được lưu theo định dạng DuckLake
-
Giấy phép của DuckLake là gì?
- Được phát hành theo giấy phép MIT
1 bình luận
Ý kiến trên Hacker News
Có một điểm tôi luôn thấy tiếc ở Parquet, đó là phần liên quan đến
ranged partitioning, thứ mà nhiều hệ “data lake / lakehouse” khác nhau đã tự giải quyết theo cách riêng nên không tương thích với nhau. Ứng dụng của tôi gần như khớp hoàn hảo với Parquet, nhưng xử lý dữ liệu như log chuỗi thời gian, nơi timestamp không phân bố đồng đều. Cột partition thì theo kiểu Hive partitioning, đồng thời lại được chia tự nhiên theo timestamp. Vấn đề là Hive partitioning không hỗ trợ điều này, nên các công cụ truy vấn chính không thể import đúng cấu trúc dữ liệu của tôi. Hoặc phải đưa vào những cách thừa thãi như cột theo ngày, hoặc cứ chất file lên thì hiệu năng và chi phí đều tệ. Iceberg, Delta Lake v.v. có hỗ trợ ranged partitioning, nhưng tôi không cần mức độ phức tạp như vậy, mà chỉ mong có một quy ước chuẩn hóa đơn giản hơn cho tên file hoặc tên thư mục. Ngoài ra, các định dạng như Parquet row, Arrow row, Thrift, protobuf gần giống nhau nhưng không hoàn toàn giống hệt; tôi nghĩ nếu có một định dạng nhị phân đi kèm cho single row hoặc row stream thì khả năng tương tác giữa nhiều công cụ sẽ tốt hơn nhiềuTôi tự hỏi liệu chỉ riêng footer metadata của file Parquet đã đủ để lấy thông tin cần thiết chưa. Metadata có chứa timestamp nhỏ nhất/lớn nhất của cột tương ứng, nên khi truy vấn, công cụ query chỉ cần đọc metadata đó là có thể quyết định có đọc file hay không, từ đó tránh các lần đọc không cần thiết
Dữ liệu thời gian rất khó xử lý, nhưng tùy cách làm thì có thể tránh được. Thay vì truy vấn trực tiếp chuỗi thời gian gốc, bạn có thể chuẩn hóa timestamp ngay ở bước xử lý sự kiện trước khi lưu, điều này khá hữu ích. Dựa trên sliding window để tìm điểm bắt đầu của sự kiện và điều chỉnh offset, có thể xác định vị trí chuỗi thời gian quay về mốc chuẩn (0), rồi dùng đó làm đơn vị sự kiện
Hive hỗ trợ hai kiểu partitioning là injected và dynamic. Có thể dùng cột hour theo thời gian UNIX làm partition key, tức số nguyên tăng thêm 3600 giây kể từ epoch. Có thể bạn sẽ cần chỉ rõ phạm vi partition cần đọc ở query engine, nhưng vẫn có thể dùng trong truy vấn theo dạng
datepartition >= a AND datepartition < b. Iceberg thì cho phép dùng trực tiếp phạm vi timestamp đơn giản hơn nhiều, và tự động loại bỏ các partition không cần metadataỞ các thư viện low-level của arrow/parquet, bạn có thể điều khiển trực tiếp row group và data page. Tôi từng dùng crate
arrow-rsvà cải thiện tốc độ truy vấn file hơn 10 lần. Có file có ít row group, có file có rất nhiều, nhưng nếu có thể nhanh chóng bỏ qua đúng những row group không cần thì skew không còn là vấn đề. Tuy nhiên cần lưu ý là số row group trên mỗi file bị giới hạn ở2^15Vấn đề này gần với giới hạn của Hive hơn là vấn đề của Parquet. Muốn xem thông tin min, max của cột thì vẫn phải mở file Parquet, nhưng nếu dữ liệu không nằm trong phạm vi thì sẽ không phát sinh thêm request nào. Nếu tận dụng loại metadata này ở tầng cao hơn, chẳng hạn trong DuckLake, thì sẽ hiệu quả hơn
Một trong những điều khó chịu nhất với Iceberg (Delta Lake cũng tương tự, nhưng cá nhân tôi thấy Iceberg còn khó hơn) là rất khó thử trong notebook hoặc môi trường local. Delta Lake có vài implementation bằng Python nhưng bị phân mảnh, còn Iceberg thì khá phiền vì phải setup cụm JVM các kiểu. Tôi từng định dùng tổ hợp sqlite/postgres + duckdb + parquet để lưu vào blob storage, nhưng cũng khá vất vả. Phía DuckDB thì chạy ngay không cần khổ sở như vậy, và mở rộng rất tự nhiên đến mức dữ liệu vừa phải. Đội DuckDB hiểu rất rõ lĩnh vực này, nên tôi thực sự rất kỳ vọng
Không biết bạn đã dùng thử PyIceberg chưa. Đây là implementation thuần Python và hoạt động khá tốt. Nó cũng hỗ trợ SQL Catalog và catalog in-memory dựa trên SQLite
https://py.iceberg.apache.org/
Có một hướng dẫn setup từng bước với S3 và RDS. Chuyển sang sqlite local chắc cũng không khó
https://www.definite.app/blog/cloud-iceberg-duckdb-aws
Thật sự có thể thử local rất dễ. Trong marimo notebook chỉ cần vài dòng code là được (lưu ý: tôi là nhà phát triển marimo)
https://www.youtube.com/watch?v=x6YtqvGcDBY
Tôi đang cân nhắc tạo một Helm chart chạy tốt với k3s. Nếu dùng datapains thì cũng có thể dựng trino khá dễ, và chỉ cần chỉnh thêm chút là có thể chạy cả hivemetastore. Tôi đã thử nghiệm kết nối Iceberg connector với trino để kiểm tra toàn bộ luồng hoạt động. Cấu trúc là load dữ liệu vào hive, cho trino trỏ tới cùng bảng đó, rồi dùng
selectđểinsertvào iceberg. Nếu phía DuckDB đưa ra được một môi trường chạy đơn giản đến mức này, họ có lẽ còn có thể giành vị thế dẫn dắt trong ngànhdelta-io(dựa trêndeltalake-r) chạy local rất dễ. Chỉ cần cài bằng pip là có thể viết catalog và file ngayhttps://delta-io.github.io/delta-rs/
Bài này chỉ ra rất đúng một phê bình sắc bén về Iceberg — đằng nào cũng đang dùng cơ sở dữ liệu, vậy tại sao lại phải nhét metadata vào file rồi xử lý nó? DuckLake có lẽ sẽ không dễ thành công rộng khắp vượt ra ngoài DuckDB, nhưng cuối cùng có thể cấu trúc sẽ chuyển sang chỗ catalog đảm nhiệm cả metadata, và format Iceberg hiện tại rồi sẽ chỉ còn là một khoảnh khắc trong lịch sử
Các hệ Lakehouse hiện có (như Iceberg) lưu thông tin bảng quan trọng như schema/danh sách file dưới dạng các file metadata nhỏ rải rác trên object storage như S3. Vì vậy những việc như lập kế hoạch truy vấn hay cập nhật bảng cần rất nhiều network call, vừa chậm vừa dễ xung đột. DuckLake đưa toàn bộ metadata vào một cơ sở dữ liệu SQL nhanh và có tính giao dịch cao, nên có thể lấy toàn bộ thông tin cần thiết chỉ bằng một truy vấn duy nhất, nhờ đó hiệu quả và độ tin cậy đều tốt hơn rất nhiều
Tuyên ngôn về DuckLake: https://ducklake.select/manifesto/
Tôi đang tự phát triển một “poor man’s datalake” nội bộ bằng Python binding của
deltalake-rsvà duck db. Cấu trúc là lưu file parquet trong blob storage. Tuy nhiên tôi luôn gặp vấn đề với concurrent write. Việc cloud function định kỳ kéo dữ liệu từ API thì không sao. Nhưng nếu chạy backfill nhiều lần, nó có thể chạy đồng thời với hàm timer và có nguy cơ xung đột. Đặc biệt là khi queue backfill có hàng trăm tác vụ và worker bị bão hòa thì càng nặngCó cách là thêm suffix ngẫu nhiên vào cuối tên file
Nếu đặt lease tạm thời trên file json trước khi write, rồi quản lý các request write bằng queue, thì có thể tránh được xung đột
Một giải pháp cạnh tranh giải quyết các giới hạn của Iceberg, đặc biệt là vấn đề quản lý metadata (ví dụ Snowflake dùng FoundationDB để quản lý metadata, còn Iceberg thì dùng cả blob storage)
https://quesma.com/blog-detail/apache-iceberg-practical-limitations-2025
Tôi cũng có ấn tượng tương tự, nhưng xem video thì DuckLake không phải đối thủ cạnh tranh trực tiếp
https://youtu.be/zeonmOO9jm4?t=4032
DuckLake chỉ ghi manifest/metadata file cho Iceberg khi cần để đồng bộ, và cũng đã hỗ trợ đọc dữ liệu Iceberg sẵn. Nó là một cải tiến cho các vấn đề cốt lõi của Iceberg hơn là một sản phẩm cạnh tranh riêng biệt; cấu trúc của nó là tích hợp hai chiều gọn gàng với Iceberg
Metadata bị phình to đến mức nào còn tùy tình huống mà hoàn toàn có thể quản lý được
Trước đây, với schema lớn thì mục cuối cùng từng là vấn đề. Hầu hết engine đều hỗ trợ quản lý bằng các công cụ như compaction, snapshot export v.v., dù cũng có phần là trách nhiệm của người dùng. S3 table cũng cung cấp một phần tính năng quản lý. Nếu metadata chỉ cỡ 1~5MB thì thật ra không thành vấn đề. Tốc độ commit phụ thuộc vào kích thước metadata và số lượng writer. Tôi cũng từng xử lý metadata vượt 1GB bằng script tự viết — thường chỉ cần dọn các snapshot đã bị ghi đè (việc xóa file thực tế giao cho bucket policy) hoặc dọn các phiên bản schema cũ là giải quyết được
Rốt cuộc, muốn xây dựng cơ sở dữ liệu cho ra hồn thì phải dựng nó như một cơ sở dữ liệu thực thụ. Tôi rất nể đội DuckDB
Tôi tò mò về mối quan hệ với Mother Duck(https://motherduck.com/). Đây là công ty làm “DuckDB-powered data warehousing”, và bắt đầu trước DuckLake
MotherDuck và DuckLake sẽ được tích hợp với nhau rất tốt. Dữ liệu MotherDuck sẽ được lưu trong DuckLake để tăng khả năng mở rộng, concurrency và tính nhất quán, đồng thời các công cụ bên thứ ba cũng có thể truy cập underlying data. Chúng tôi đã phát triển phần này trong vài tháng gần đây và sẽ sớm công bố thêm thông tin
MotherDuck là dịch vụ tự động sắp xếp dữ liệu khi bạn tải lên và cung cấp giao diện dữ liệu bằng DuckDB. Nếu bạn muốn nhiều đặc tính kiểu lakehouse hơn, tích hợp blob storage, tích hợp sâu hơn với DuckLake, hoặc muốn lưu metadata trong MotherDuck, thì có thể dùng DuckLake
MotherDuck là dịch vụ host duckdb trên cloud, còn DuckLake là một hệ thống mở hơn rất nhiều. Với DuckLake, bạn có thể xây dựng warehouse nhiều instance ở nhiều môi trường như S3 hay EC2, ở quy mô petabyte, với nhiều reader/writer, tất cả đều có tính giao dịch. MotherDuck chỉ cho phép một writer tại một thời điểm, read replica có độ trễ khoảng 1 phút và không có tính giao dịch. Nhiều instance cũng không thể đồng thời ghi vào các bảng khác nhau. DuckLake còn cung cấp tách biệt lưu trữ và tính toán, cùng một lớp metadata có tính giao dịch cao
Tôi rất yêu duckDB và thấy DuckLake cũng cực kỳ tuyệt. Có một điều tôi tò mò: nếu bắt đầu dùng từ bây giờ, trong khi công ty đang chạy Snowflake, thì các analyst sẽ phải cài duckdb + extension trên máy local và trỏ vào blob store cùng cơ sở dữ liệu cho datalake extension (ví dụ duckdb chạy trên một VM). Tôi muốn hiểu là khi chạy truy vấn thì compute diễn ra ở đâu, và nếu muốn làm những tác vụ lớn hơn thì phải làm thế nào. Liệu mô hình đó có phải là mọi người ssh vào một VM duckdb khổng lồ để chạy query hay không; mong được giải thích thêm về phần này