Apache Iceberg dường như đã gây bão trong thế giới dữ liệu. Ban đầu được ươm tạo tại Netflix bởi Ryan Blue, cuối cùng nó đã được chuyển đến Tổ chức Phần mềm Apache nơi nó hiện đang cư trú. Về cốt lõi, nó là một định dạng bảng mở cho các tập dữ liệu phân tích ở quy mô lớn (nghĩ rằng hàng trăm TB đến hàng trăm PB).
Nó là một định dạng tương thích với nhiều động cơ. Điều đó có nghĩa là Spark, Trino, Flink, Presto, Hive và Impala đều có thể hoạt động độc lập và đồng thời trên tập dữ liệu. Nó hỗ trợ ngôn ngữ chung về phân tích dữ liệu, SQL, cũng như các tính năng chính như tiến hóa lược đồ đầy đủ, phân vùng ẩn, du hành thời gian, khôi phục và nén dữ liệu.
Bài đăng này tập trung vào cách Iceberg và MinIO bổ sung cho nhau và cách các khung phân tích khác nhau (Spark, Flink, Trino, Dremio và Snowflake) có thể tận dụng cả hai.
Mặc dù Apache Hive là một bước tiến quan trọng vào thời điểm đó, nhưng cuối cùng thì nó cũng bắt đầu xuất hiện các vết nứt khi các ứng dụng phân tích trở nên nhiều hơn, đa dạng hơn và phức tạp hơn. Để đạt được hiệu suất, dữ liệu cần được duy trì trong các thư mục và những thư mục đó cần được quản lý liên tục. Điều này dẫn đến một cơ sở dữ liệu của các thư mục. Điều đó đã giải quyết vấn đề về vị trí của dữ liệu, nhưng nó lại đưa ra vấn đề về trạng thái của bảng đó - hiện ở hai nơi (cơ sở dữ liệu của các thư mục và hệ thống tệp).
Điều này hạn chế những gì bạn có thể làm và tính linh hoạt tồn tại — cụ thể là đối với các thay đổi, điều không thể được đảm bảo ở cả hai nơi chỉ bằng một thao tác.
Hãy tưởng tượng một lượng lớn dữ liệu trong nhiều năm được phân vùng theo ngày. Năm được chia thành tháng và tuần, và nếu tuần được chia thành ngày, ngày thành giờ, v.v. - thì danh sách thư mục sẽ bùng nổ. Hive Metastore (HMS) là một RDBMS giao dịch. Hệ thống tệp (HDFS) không phải là giao dịch. Khi thông tin phân vùng được thay đổi, nó yêu cầu giải trí cả kho lưu trữ phân vùng và hệ thống tệp.
Vấn đề không bền vững và không có số lượng bản vá nào sẽ giải quyết được các vấn đề cố hữu. Trên thực tế, những thách thức chỉ tăng tốc với tốc độ tăng trưởng dữ liệu.
Một trong những điểm bán hàng chính xung quanh kiến trúc data lakehouse là nó hỗ trợ nhiều công cụ và khung phân tích. Ví dụ: bạn cần hỗ trợ cả ELT (Trích xuất, Tải, Chuyển đổi) và ETL (Trích xuất, Chuyển đổi, Tải). Bạn cần hỗ trợ các loại khối lượng công việc kinh doanh thông minh, phân tích kinh doanh và AI/ML. Bạn cần giao tiếp thành công với cùng một nhóm bảng theo cách an toàn và có thể dự đoán được. Điều này có nghĩa là nhiều công cụ như Spark, Flink, Trino, Arrow và Dask đều cần phải được gắn kết theo một cách nào đó trong một kiến trúc gắn kết.
Một nền tảng đa công cụ chứa dữ liệu hiệu quả đồng thời cho phép mỗi công cụ thành công là điều mà thế giới phân tích đang khao khát và là điều mà kiến trúc Iceberg và Data Lakehouse mang lại.
Điều này không đơn giản và có rất nhiều thách thức với nó; không có cách nào dễ dàng để sử dụng nhiều công cụ với bản cập nhật dữ liệu đáng tin cậy. Nhưng ngay cả bây giờ chúng tôi có hai hoặc ba định dạng cung cấp các bản cập nhật đáng tin cậy, vẫn còn nhiều nhầm lẫn và có vấn đề trong lĩnh vực này.
Yêu cầu hiện đại trông như thế này:
Lưu trữ bảng trung tâm : Lưu trữ dữ liệu độc lập với máy tính trở thành một quyết định kiến trúc quan trọng. Lý do nó quan trọng là vì dữ liệu có lực hấp dẫn và nó kéo chúng ta về vị trí của dữ liệu. Vì vậy, nếu dữ liệu của chúng tôi hoàn toàn nằm trong một nhà cung cấp hoặc nhà cung cấp đám mây thì chúng tôi chỉ bị ràng buộc với nhà cung cấp hoặc nhà cung cấp đám mây đó. Điều này vốn đã có vấn đề khi các hệ thống đó được đóng hoặc chuyên về thiết kế. Phần mềm mở trở thành yêu cầu đối với các kiến trúc hiện đại.
Điện toán di động : Một yêu cầu hiện đại khác là khả năng đưa các công cụ điện toán của bạn đến một nhà cung cấp/nhà cung cấp đám mây khác hoặc tận dụng các công cụ điện toán chuyên dụng. Trong khi nhiều người tập trung vào trọng tâm (dữ liệu), doanh nghiệp cũng cần tính di động cho logic, mã và SQL.
Kiểm soát truy cập : Hầu hết các doanh nghiệp gặp thách thức lớn để có chính sách ủy quyền nhất quán trên các công cụ. Tuy nhiên, nó không chỉ là kiến trúc, vì việc thực thi thành công và có thể lặp lại các chính sách này trên nhiều công cụ trở thành một mệnh lệnh vận hành.
Duy trì cấu trúc : Một trong những nguồn công việc lớn nhất của con người mà chúng tôi đã thấy trong vài năm qua là làm mất cấu trúc dữ liệu khi nó được chuyển đi nơi khác. Một ví dụ hoàn hảo từng là Snowflake. Quá trình di chuyển dữ liệu sang Snowflake là quy trình thủ công và việc giới thiệu bộ dữ liệu của bên thứ ba cũng dẫn đến việc làm lại do các định dạng tệp khác nhau và các thay đổi về định dạng trong quá trình di chuyển.
Apache Iceberg được thiết kế từ đầu với hầu hết các thách thức và mục tiêu được đề cập ở trên làm cơ sở để triển khai định dạng bảng mở. Nó giải quyết các thách thức sau:
Đừng di chuyển dữ liệu; nhiều động cơ nên hoạt động trơn tru
Hỗ trợ các công việc hàng loạt, phát trực tuyến và đột xuất
Hỗ trợ mã từ nhiều ngôn ngữ, không chỉ các khung công tác JVM
Các giao dịch đáng tin cậy với các bảng SQL nơi chúng tôi có khả năng thực hiện các hoạt động CRUD một cách đáng tin cậy
Việc tách các mối quan tâm khỏi các bảng thực cung cấp sự tách biệt đó
Apache Iceberg giữ các bản ghi của nó trong bộ lưu trữ đối tượng — không giống như Apache Hive. Iceberg cho phép hành vi SQL được tận dụng bởi nhiều công cụ và nó được thiết kế cho các bảng lớn. Trong sản xuất, nơi một bảng có thể chứa hàng chục petabyte dữ liệu, điều này rất quan trọng. Ngay cả các bảng nhiều petabyte cũng có thể được đọc từ một nút duy nhất mà không cần một công cụ SQL phân tán để sàng lọc siêu dữ liệu bảng.
Nguồn: https://iceberg.apache.org/spec/
Iceberg có một quy tắc bất thành văn, là vô hình khi được sử dụng trong ngăn xếp Dữ liệu lớn. Triết lý này xuất phát từ không gian bảng SQL, nơi mà chúng ta không bao giờ nghĩ đến những gì bên dưới các bảng SQL. Như bất kỳ học viên nào cũng biết, điều này đơn giản không xảy ra khi làm việc với các bảng giống như Hadoop và Hive.
Iceberg giữ cho nó đơn giản theo hai cách. Đầu tiên, tránh những bất ngờ khó chịu khi thay đổi được thực hiện đối với bảng. Ví dụ: một thay đổi sẽ không bao giờ mang lại dữ liệu đã bị xóa và xóa. Thứ hai, Iceberg giảm chuyển đổi ngữ cảnh vì những gì bên dưới bảng không quan trọng - điều quan trọng là công việc phải hoàn thành.
FileIO là giao diện giữa thư viện Iceberg cốt lõi và bộ nhớ cơ bản. FileIO được tạo ra như một cách để Iceberg hoạt động trong một thế giới nơi tính toán và lưu trữ phân tán được phân tách. Hệ sinh thái Hadoop kế thừa yêu cầu các cấu trúc phân vùng và đường dẫn phân cấp, trên thực tế, hoàn toàn trái ngược với các phương pháp được sử dụng để đạt được tốc độ và quy mô trong thế giới lưu trữ đối tượng.
Hadoop và Hive là các mô hình chống đối để lưu trữ đối tượng gốc trên đám mây có hiệu suất cao và có thể mở rộng. Các ứng dụng kho dữ liệu dựa trên API S3 để tương tác với MinIO có thể dễ dàng mở rộng quy mô thành hàng nghìn giao dịch mỗi giây trên hàng triệu hoặc hàng tỷ đối tượng. Bạn có thể tăng hiệu suất đọc và ghi bằng cách xử lý song song nhiều yêu cầu đồng thời. Bạn thực hiện điều này bằng cách thêm các tiền tố — một chuỗi ký tự là tập hợp con của tên đối tượng, bắt đầu bằng ký tự đầu tiên — vào các nhóm và sau đó viết các thao tác song song, mỗi thao tác mở một kết nối trên mỗi tiền tố.
Ngoài ra, sự phụ thuộc của Hadoop vào các thư mục hệ thống tệp không chuyển thành lưu trữ đối tượng – thật khó để tổ chức các tập dữ liệu về mặt vật lý vào các thư mục khác nhau và xử lý chúng theo đường dẫn khi các đường dẫn không tồn tại. Hadoop dựa vào một hệ thống tệp để xác định tập dữ liệu và cung cấp các cơ chế khóa để giải quyết xung đột và đồng thời. Ngoài ra, trong hệ sinh thái Hadoop, các công việc xử lý hoạt động đổi tên phải là nguyên tử. Điều này là không thể khi sử dụng API S3 vì đổi tên thực sự là hai thao tác: sao chép và xóa. Thật không may, kết quả là không có sự tách biệt giữa đọc và viết, có thể dẫn đến xung đột, va chạm và không nhất quán.
Ngược lại, Iceberg được thiết kế để chạy hoàn toàn trừu tượng từ lưu trữ vật lý bằng cách sử dụng lưu trữ đối tượng. Tất cả các vị trí là "rõ ràng, không thay đổi và tuyệt đối" như được định nghĩa trong siêu dữ liệu. Iceberg theo dõi toàn bộ trạng thái của bảng mà không cần các thư mục tham chiếu. Việc sử dụng siêu dữ liệu để tìm bảng nhanh hơn đáng kể so với việc liệt kê toàn bộ hệ thống phân cấp bằng API S3. Không có đổi tên - một cam kết chỉ cần thêm các mục mới vào bảng siêu dữ liệu.
API FileIO thực hiện các hoạt động siêu dữ liệu trong giai đoạn lập kế hoạch và cam kết. Các tác vụ sử dụng FileIO để đọc và ghi các tệp dữ liệu cơ bản và vị trí của các tệp này được bao gồm trong siêu dữ liệu bảng trong một lần xác nhận. Chính xác cách thức công cụ thực hiện điều này phụ thuộc vào việc triển khai FileIO. Đối với các môi trường cũ, HadoopFileIO
đóng vai trò là lớp bộ điều hợp giữa triển khai Hệ thống tệp Hadoop hiện có và API FileIO trong Iceberg.
Thay vào đó, chúng tôi sẽ tập trung vào S3FileIO
vì đây là triển khai S3 gốc. Chúng tôi không cần phải mang theo hành trình Hadoop bên mình khi chúng tôi xây dựng ngôi nhà ven hồ trên nền tảng đám mây của mình. Theo Iceberg FileIO: Cloud Native Tables , các ưu điểm của việc triển khai S3 gốc bao gồm:
Hành vi hợp đồng: Việc triển khai Hệ thống tệp Hadoop có hành vi hợp đồng nghiêm ngặt dẫn đến các yêu cầu bổ sung (kiểm tra sự tồn tại, giải mã thư mục và đường dẫn) làm tăng thêm chi phí và độ phức tạp. Iceberg sử dụng các đường dẫn duy nhất và có thể định địa chỉ đầy đủ để tránh sự phức tạp bổ sung.
Tải lên được tối ưu hóa: S3FileIO
tối ưu hóa cho lưu trữ/bộ nhớ bằng cách tải lên dữ liệu dần dần để giảm thiểu mức tiêu thụ ổ đĩa cho các tác vụ lớn và duy trì mức tiêu thụ bộ nhớ thấp khi nhiều tệp được mở để xuất.
Tùy chỉnh ứng dụng khách S3: ứng dụng khách sử dụng phiên bản AWS SDK chính mới nhất (v2) và cho phép người dùng tùy chỉnh hoàn toàn ứng dụng khách để sử dụng với S3 (bao gồm mọi điểm cuối tương thích API S3).
Hiệu suất tuần tự hóa: Quá trình xử lý tác vụ với HadoopFileIO
yêu cầu tuần tự hóa cấu hình Hadoop, quá trình này khá lớn và trong các trường hợp suy biến có thể làm chậm quá trình xử lý và dẫn đến nhiều chi phí hoạt động hơn dữ liệu được xử lý.
Giảm sự phụ thuộc: Việc triển khai Hệ thống tệp Hadoop giới thiệu một cây phụ thuộc lớn và việc triển khai đơn giản hóa làm giảm độ phức tạp của việc đóng gói tổng thể.
Iceberg cung cấp khả năng tích hợp với các dịch vụ AWS khác nhau thông qua mô- đun iceberg-aws , đi kèm với thời gian chạy Spark và Flink cho tất cả các phiên bản từ 0.11.0
trở đi. Iceberg cho phép người dùng ghi dữ liệu vào S3 thông qua S3FileIO
. Khi sử dụng S3FileIO
, các danh mục được định cấu hình để sử dụng API S3 bằng cách sử dụng thuộc tính danh mục io-impl
. S3FileIO
sử dụng các tính năng mới nhất của S3 để bảo mật được tối ưu hóa (danh sách kiểm soát truy cập S3, cả ba chế độ mã hóa phía máy chủ S3) và hiệu suất (tải lên nhiều phần liên tục), do đó được đề xuất cho các trường hợp sử dụng bộ nhớ đối tượng.
Tại thời điểm này, Spark là công cụ điện toán giàu tính năng nhất để làm việc với Iceberg, vì vậy hướng dẫn này tập trung vào việc sử dụng Spark và Spark-SQL để hiểu các khái niệm và tính năng của Iceberg. Trên Ubuntu 20.04, chúng tôi sẽ cài đặt và định cấu hình Java, PostgreSQL dưới dạng con trỏ danh mục hoặc siêu dữ liệu, Spark và MinIO – đồng thời tải xuống và định cấu hình cẩn thận các phụ thuộc Java. Sau đó, chúng tôi sẽ chạy Spark-SQL để tạo, điền, truy vấn và sửa đổi bảng. Chúng ta cũng sẽ xem qua một số điều tuyệt vời mà bạn có thể thực hiện với Iceberg, chẳng hạn như tiến hóa lược đồ, làm việc với các phân vùng ẩn, du hành thời gian và khôi phục. Sau mỗi bước, chúng tôi bao gồm một ảnh chụp màn hình của thùng Iceberg trong MinIO để bạn có thể xem những gì đang diễn ra đằng sau hậu trường.
Tải xuống và khởi động Máy chủ MinIO. Ghi lại địa chỉ IP, cổng TCP, khóa truy cập và khóa bí mật.
Tải xuống và cài đặt Máy khách MinIO.
Sử dụng Máy khách MinIO để đặt bí danh và tạo thùng cho Iceberg
mc alias set minio http://<your-MinIO-IP:port> <your-MinIO-access-key> <your-MinIO-secret-key> mc mb minio/iceberg Bucket created successfully `myminio/iceberg`.
Bạn sẽ cần tải xuống và định cấu hình Spark để sử dụng Lưu trữ Java (JAR) bắt buộc nhằm kích hoạt các chức năng khác nhau như Hadoop, AWS S3 và JDBC. Bạn cũng cần có phiên bản phù hợp của từng tệp JAR và tệp cấu hình được yêu cầu trong PATH và CLASSPATH. Thật không may, rất dễ gọi các phiên bản JAR khác nhau và không theo dõi được JAR nào bạn đang chạy và do đó gặp phải sự không tương thích dừng hiển thị.
Cài đặt Java Runtime nếu bạn chưa cài đặt. Đối với Ubuntu 20.04, lệnh là
sudo apt install curl mlocate default-jdk -y
Tải xuống và định cấu hình PostgreSQL để chạy dưới dạng dịch vụ hệ thống
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add - sudo apt-get update sudo apt-get -y install postgresql sudo systemctl start postgresql.service
Chúng tôi sẽ tạo một vai trò icebergcat
với tư cách là siêu người dùng, đặt mật khẩu và tạo cơ sở dữ liệu icebergcat
sudo -u postgres createuser --interactive ALTER ROLE icebergcat PASSWORD 'minio'; sudo -u postgres createdb icebergcat
Đăng nhập vào cơ sở dữ liệu để xác minh nó hoạt động, bạn sẽ được nhắc nhập mật khẩu:
psql -U icebergcat -d icebergcat -W -h 127.0.0.1
Tải xuống, giải nén và di chuyển Apache Spark
$ wget https://dlcdn.apache.org/spark/spark-3.2.1/spark-3.2.1-bin-hadoop3.2.tgz $ tar zxvf spark-3.2.1-bin-hadoop3.2.tgz $ sudo mv spark-3.2.1-bin-hadoop3.2/ /opt/spark
Đặt môi trường Spark bằng cách thêm phần sau vào ~/.bashrc
rồi khởi động lại trình bao để áp dụng các thay đổi.
export SPARK_HOME=/opt/spark export PATH=$PATH:$SPARK_HOME/bin:$SPARK_HOME/sbin bash -l
Các tệp .jar sau đây là bắt buộc. Tải xuống và sao chép các tệp .jar vào bất kỳ vị trí cần thiết nào trên máy Spark, chẳng hạn như /opt/spark/jars
.
aws-java-sdk-bundle/1.11.901.jar (hoặc cao hơn) là cần thiết để hỗ trợ giao thức S3.
$ wget https://repo1.maven.org/maven2/software/amazon/awssdk/bundle/2.17.230/bundle-2.17.230.jar
iceberg-spark-runtime-3.2_2.12.jar là bắt buộc.
$ wget https://repo.maven.apache.org/maven2/org/apache/iceberg/iceberg-spark-runtime-3.1_2.12/0.13.2/iceberg-spark-runtime-3.1_2.12-0.13.2.jar
Bắt đầu một máy chủ chính độc lập Spark
$ start-master.sh starting org.apache.spark.deploy.master.Master, logging to /opt/spark/logs/spark-msarrel-org.apache.spark.deploy.master.Master-1-<Your-Machine-Name>.out
Mở trình duyệt và truy cập http: // Your-IPaddress:7077
Spark còn sống tại spark://<Your-Machine-Name>:7077
Bắt đầu quy trình công nhân Spark
$ /opt/spark/sbin/start-worker.sh spark://<Your-Machine-Name>:7077 starting org.apache.spark.deploy.worker.Worker, logging to /opt/spark/logs/spark-msarrel-org.apache.spark.deploy.worker.Worker-1-<Your-Machine-Name>.out
Khởi tạo môi trường trước khi khởi chạy Spark-SQL.
export AWS_ACCESS_KEY_ID=minioadmin export AWS_SECRET_ACCESS_KEY=minioadmin export AWS_S3_ENDPOINT=10.0.0.10:9000 export AWS_REGION=us-east-1 export MINIO_REGION=us-east-1 export DEPENDENCIES="org.apache.iceberg:iceberg-spark-runtime-3.2_2.12:0.13.2" export AWS_SDK_VERSION=2.17.230 export AWS_MAVEN_GROUP=software.amazon.awssdk export AWS_PACKAGES=( "bundle" "url-connection-client" ) for pkg in "${AWS_PACKAGES[@]}"; do export DEPENDENCIES+=",$AWS_MAVEN_GROUP:$pkg:$AWS_SDK_VERSION" done
Chạy lệnh sau để khởi chạy Spark-SQL với Iceberg bằng cách sử dụng PostgreSQL cho siêu dữ liệu và hỗ trợ API S3, cần thiết cho MinIO. Ngoài ra, bạn có thể đặt cấu hình bằng tệp spark-defaults.conf
cục bộ của mình
$ spark-sql --packages $DEPENDENCIES \ --conf spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions \ --conf spark.sql.catalog.demo=org.apache.iceberg.spark.SparkCatalog --conf spark.sql.catalog.my_catalog.catalog-impl=org.apache.iceberg.jdbc.JdbcCatalog \ --conf spark.sql.catalog.my_catalog.uri=jdbc:postgresql://127.0.0.1:5432/icebergcat \ --conf spark.sql.catalog.my_catalog.jdbc.user=icebergcat \ --conf spark.sql.catalog.my_catalog.jdbc.password=minio \ --conf spark.sql.catalog.my_catalog.warehouse=s3://iceberg \ --conf spark.sql.catalog.my_catalog.io-impl=org.apache.iceberg.aws.s3.S3FileIO \ --conf spark.sql.catalog.my_catalog.s3.endpoint=http://10.0.0.10:9000 \ --conf spark.sql.catalog.spark_catalog=org.apache.iceberg.spark.SparkSessionCatalog \ --conf spark.sql.defaultCatalog=my_catalog \ --conf spark.eventLog.enabled=true \ --conf spark.eventLog.dir=/home/iceicedata/spark-events \ --conf spark.history.fs.logDirectory= /home/iceicedata/spark-events \ --conf spark.sql.catalogImplementation=in-memory
Một vài lưu ý quan trọng về cấu hình này
my_catalog
sử dụng JDBC để kết nối với PostgreSQL trên một địa chỉ IP nội bộ và sử dụng bảng icebergcat
cho siêu dữ liệu.S3FileIO
để truy cập nó.Tiếp theo, chúng ta sẽ tạo một bảng đơn giản.
CREATE TABLE my_catalog.my_table ( id bigint, data string, category string) USING iceberg LOCATION 's3://iceberg' PARTITIONED BY (category);
Đây là một cải tiến lớn về hiệu suất mà Iceberg cung cấp với S3FileIO. Đây là một sự nhẹ nhõm tuyệt vời đối với những người trong chúng ta, những người đã phải chịu đựng hiệu suất chậm khi sử dụng bố cục lưu trữ Hive truyền thống với S3 do các yêu cầu điều tiết dựa trên tiền tố đối tượng. Rõ ràng là việc tạo bảng Athena/Hive được phân vùng trên AWS S3 có thể mất từ 30-60 phút. Theo mặc định, Iceberg sử dụng bố cục lưu trữ Hive nhưng có thể được chuyển sang sử dụng ObjectStoreLocationProvider
.
Với ObjectStoreLocationProvider
, hàm băm xác định được tạo cho mỗi tệp được lưu trữ, với hàm băm được nối trực tiếp sau write.data.path
. Điều này đảm bảo các tệp được ghi vào bộ lưu trữ đối tượng tương thích với S3 được phân phối đồng đều trên nhiều tiền tố trong bộ chứa S3, dẫn đến điều tiết tối thiểu và thông lượng tối đa cho các hoạt động IO liên quan đến S3. Khi sử dụng ObjectStoreLocationProvider
, việc có một write.data.path
ngắn và được chia sẻ trên các bảng Iceberg của bạn sẽ cải thiện hiệu suất. Nhiều hơn nữa đã được thực hiện trong Iceberg để cải thiện hiệu suất và độ tin cậy trên Hive .
CREATE TABLE my_catalog.my_table ( id bigint, data string, category string) USING iceberg OPTIONS ( 'write.object-storage.enabled'=true, 'write.data.path'='s3://iceberg') PARTITIONED BY (category);
Nhìn vào Bảng điều khiển MinIO, chúng tôi thấy rằng một đường dẫn đã được tạo dưới thùng iceberg
của chúng tôi cho my_table
Nhóm chứa một đường dẫn metadata
Tại thời điểm này, không có dữ liệu trong bảng, chỉ có siêu dữ liệu mô tả bảng. Ngoài ra còn có một con trỏ tới siêu dữ liệu này được lưu trữ trong bảng danh mục Iceberg trong PostgreSQL. Spark-SQL (công cụ truy vấn) tìm kiếm danh mục Iceberg ( my_catalog
) theo tên bảng ( my_table
) và truy xuất URI tới tệp siêu dữ liệu hiện tại.
Chúng ta hãy xem tệp siêu dữ liệu đầu tiên, nơi lưu trữ thông tin về lược đồ, phân vùng và ảnh chụp nhanh của bảng. Mặc dù tất cả ảnh chụp nhanh được xác định, current-snapshot-id
cho công cụ truy vấn biết ảnh chụp nhanh nào sẽ được sử dụng, sau đó công cụ truy vấn tìm kiếm giá trị đó trong mảng snapshots
, lấy giá trị của manifest-list
của ảnh chụp nhanh đó và mở tệp kê khai trong đó danh sách, theo thứ tự. Lưu ý rằng ví dụ của chúng tôi chỉ có một ảnh chụp nhanh vì bảng vừa được tạo và không có bảng kê khai vì chúng tôi chưa chèn dữ liệu.
{ "format-version" : 1, "table-uuid" : "b72c46d1-0648-4e02-aab3-0d2853c97363", "location" : "s3://iceberg/my_table", "last-updated-ms" : 1658795119167, "last-column-id" : 3, "schema" : { "type" : "struct", "schema-id" : 0, "fields" : [ { "id" : 1, "name" : "id", "required" : false, "type" : "long" }, { "id" : 2, "name" : "data", "required" : false, "type" : "string" }, { "id" : 3, "name" : "category", "required" : false, "type" : "string" } ] }, "current-schema-id" : 0, "schemas" : [ { "type" : "struct", "schema-id" : 0, "fields" : [ { "id" : 1, "name" : "id", "required" : false, "type" : "long" }, { "id" : 2, "name" : "data", "required" : false, "type" : "string" }, { "id" : 3, "name" : "category", "required" : false, "type" : "string" } ] } ], "partition-spec" : [ { "name" : "category", "transform" : "identity", "source-id" : 3, "field-id" : 1000 } ], "default-spec-id" : 0, "partition-specs" : [ { "spec-id" : 0, "fields" : [ { "name" : "category", "transform" : "identity", "source-id" : 3, "field-id" : 1000 } ] } ], "last-partition-id" : 1000, "default-sort-order-id" : 0, "sort-orders" : [ { "order-id" : 0, "fields" : [ ] } ], "properties" : { "option.write.data.path" : "s3://iceberg/my_table", "owner" : "msarrel", "option.write.object-storage.enabled" : "true", "write.data.path" : "s3://iceberg/my_table", "write.object-storage.enabled" : "true" }, "current-snapshot-id" : -1, "snapshots" : [ ], "snapshot-log" : [ ], "metadata-log" : [ ] }
Tiếp theo, hãy chèn một số dữ liệu mô phỏng và xem các tệp mà Iceberg lưu trữ trong MinIO. Bên trong nhóm tảng iceberg
, hiện có các tiền tố my_table/metadata
và my_table/data
.
INSERT INTO my_catalog.my_table VALUES (1, 'a', "music"), (2, 'b', "music"), (3, 'c', "video");
Tiền tố siêu dữ liệu chứa tệp siêu dữ liệu gốc, danh sách tệp kê khai và tệp kê khai. Danh sách tệp kê khai là - bạn đoán nó rồi - một danh sách các tệp kê khai. Danh sách tệp kê khai chứa thông tin về từng tệp kê khai được bao gồm trong mỗi ảnh chụp nhanh: vị trí của tệp kê khai, ảnh chụp nhanh được thêm vào, thông tin về phân vùng và giới hạn dưới và trên cho các cột phân vùng của các tệp dữ liệu liên quan. Trong một truy vấn, công cụ truy vấn đọc giá trị của các vị trí tệp kê khai từ danh sách kê khai và mở các tệp kê khai thích hợp. Danh sách kê khai ở định dạng AVRO.
Các tệp kê khai theo dõi các tệp dữ liệu và bao gồm các chi tiết cũng như số liệu thống kê được tính toán trước về từng tệp. Điều đầu tiên được theo dõi là định dạng và vị trí tệp. Các tệp kê khai là cách Iceberg loại bỏ dữ liệu theo dõi kiểu Hive theo vị trí hệ thống tệp. Các tệp kê khai cải thiện hiệu quả và hiệu suất của việc đọc các tệp dữ liệu bằng cách bao gồm các chi tiết như tư cách thành viên phân vùng, số lượng bản ghi và giới hạn dưới và trên của mỗi cột. Số liệu thống kê được viết trong quá trình ghi và có nhiều khả năng kịp thời, chính xác và cập nhật hơn số liệu thống kê của Hive.
Khi một truy vấn CHỌN được gửi, công cụ truy vấn sẽ lấy vị trí của danh sách tệp kê khai từ cơ sở dữ liệu siêu dữ liệu. Sau đó, công cụ truy vấn đọc giá trị của các mục nhập file-path
cho từng đối tượng data-file
và sau đó mở tệp dữ liệu để thực hiện truy vấn.
Hiển thị bên dưới là nội dung của tiền tố data
, được sắp xếp theo phân vùng.
Bên trong phân vùng, có một tệp dữ liệu trên mỗi hàng của bảng.
Hãy chạy một truy vấn ví dụ:
spark-sql> SELECT count(1) as count, data FROM my_catalog.my_table GROUP BY data; 1 a 1 b 1 c Time taken: 9.715 seconds, Fetched 3 row(s) spark-sql>
Bây giờ chúng ta đã hiểu các thành phần khác nhau của bảng Iceberg và cách công cụ truy vấn hoạt động với chúng, hãy đi sâu vào các tính năng tốt nhất của Iceberg và cách tận dụng chúng trong kho dữ liệu của bạn.
Các thay đổi về tiến trình lược đồ như Thêm, Xóa, Đổi tên và Cập nhật là các thay đổi siêu dữ liệu, nghĩa là không cần thay đổi/ghi lại tệp dữ liệu để thực hiện cập nhật. Iceberg cũng đảm bảo rằng những thay đổi tiến hóa lược đồ này là độc lập và không có tác dụng phụ. Iceberg sử dụng các Id duy nhất để theo dõi từng cột trong một bảng với điều này nếu một cột mới được thêm vào, nó sẽ không bao giờ tận dụng một Id hiện có do nhầm lẫn.
Các phân vùng bảng Iceberg có thể được cập nhật trong một bảng hiện có vì các truy vấn không tham chiếu trực tiếp các giá trị phân vùng. Khi dữ liệu mới được ghi, nó sử dụng thông số kỹ thuật mới trong bố cục mới, dữ liệu được ghi trước đó với thông số kỹ thuật khác vẫn không thay đổi. Điều này gây ra lập kế hoạch tách khi bạn viết truy vấn mới. Để cải thiện hiệu suất, Iceberg sử dụng phân vùng ẩn để người dùng không cần phải viết truy vấn cho bố cục phân vùng cụ thể để nhanh chóng. Người dùng tập trung vào việc viết các truy vấn cho dữ liệu họ cần và để Iceberg cắt bớt các tệp không chứa dữ liệu phù hợp.
Một cải tiến khác rất hữu ích là thứ tự sắp xếp của Iceberg cũng có thể được cập nhật trong bảng hiện có giống như thông số phân vùng. Các công cụ khác nhau có thể chọn ghi dữ liệu theo thứ tự sắp xếp mới nhất theo thứ tự chưa sắp xếp khi việc sắp xếp quá tốn kém, dữ liệu cũ được ghi với thứ tự sắp xếp trước đó vẫn không thay đổi.
spark-sql> ALTER TABLE my_catalog.my_table > RENAME my_catalog.my_table_2;
Một vài lần đầu tiên bạn làm điều này, bạn sẽ bị choáng ngợp bởi tốc độ của nó. Điều này là do bạn không viết lại bảng, bạn chỉ đang thao tác trên siêu dữ liệu. Trong trường hợp này, chúng tôi chỉ thay đổi table_name
và Iceberg đã thực hiện việc này cho chúng tôi trong khoảng một phần mười giây.
Các thay đổi lược đồ khác không gây đau đớn như nhau:
spark-sql> ALTER TABLE my_catalog.my_table RENAME COLUMN data TO quantity; spark-sql> ALTER TABLE my_catalog.my_table ADD COLUMN buyer string AFTER quantity; spark-sql> ALTER TABLE my_catalog.my_table ALTER COLUMN quantity AFTER buyer;
Như chúng tôi đã đề cập trước đó, các phân vùng được hỗ trợ bởi các định dạng tổ ong khác, tuy nhiên Iceberg hỗ trợ phân vùng ẩn có thể xử lý các tác vụ tẻ nhạt và dễ bị lỗi trong việc tạo các giá trị phân vùng cho các hàng trong bảng. Người dùng tập trung vào việc thêm bộ lọc vào các truy vấn giải quyết các vấn đề kinh doanh và không phải lo lắng về cách phân vùng bảng. Iceberg sẽ tự động tránh đọc từ các phân vùng không cần thiết.
Iceberg xử lý sự phức tạp của việc phân vùng và thay đổi sơ đồ phân vùng của bảng cho bạn, giúp đơn giản hóa đáng kể quy trình cho người dùng cuối. Bạn có thể xác định phân vùng hoặc để Iceberg xử lý việc đó cho bạn. Iceberg thích phân vùng theo dấu thời gian, chẳng hạn như thời gian diễn ra sự kiện. Các phân vùng được theo dõi bằng ảnh chụp nhanh trong tệp kê khai. Truy vấn không còn phụ thuộc vào bố cục vật lý của bảng. Do sự tách biệt này giữa các bảng vật lý và bảng logic, các bảng Iceberg có thể phát triển các phân vùng theo thời gian khi có thêm dữ liệu. Ví dụ: việc phân vùng lại bảng Hive sẽ yêu cầu tạo một bảng mới và đọc dữ liệu cũ vào đó. Bạn cũng sẽ phải thay đổi giá trị PHẦN THAM GIA trong mọi truy vấn đơn lẻ mà bạn đã viết — thật không vui chút nào.
spark-sql> ALTER TABLE my_catalog.my_table ADD COLUMN month int AFTER category; ALTER TABLE my_catalog.my_table ADD PARTITION FIELD month;
Bây giờ chúng ta có hai lược đồ phân vùng cho cùng một bảng. Điều không thể ở Hive đã diễn ra một cách minh bạch ở Iceberg. Từ giờ trở đi, các kế hoạch truy vấn được tách ra, sử dụng lược đồ phân vùng cũ để truy vấn dữ liệu cũ và lược đồ phân vùng mới để truy vấn dữ liệu mới. Iceberg sẽ giải quyết vấn đề này cho bạn — những người truy vấn bảng không cần biết rằng dữ liệu được lưu trữ bằng hai sơ đồ phân vùng. Iceberg thực hiện điều này thông qua sự kết hợp của các mệnh đề WHERE đằng sau hậu trường và bộ lọc phân vùng giúp loại bỏ các tệp dữ liệu không khớp.
Mỗi lần ghi vào bảng Iceberg sẽ tạo ảnh chụp nhanh mới. Ảnh chụp nhanh giống như các phiên bản và có thể được sử dụng để du hành và quay ngược thời gian giống như cách chúng tôi làm với khả năng lập phiên bản MinIO. Cách quản lý ảnh chụp nhanh bằng cách đặt expireSnapshot
để hệ thống được duy trì tốt. Du hành thời gian cho phép các truy vấn có thể lặp lại sử dụng chính xác cùng một ảnh chụp bảng hoặc cho phép người dùng dễ dàng kiểm tra các thay đổi. Phục hồi phiên bản cho phép người dùng nhanh chóng khắc phục sự cố bằng cách đặt lại các bảng về trạng thái tốt.
Khi các bảng được thay đổi, Iceberg theo dõi từng phiên bản dưới dạng ảnh chụp nhanh và sau đó cung cấp khả năng du hành thời gian tới bất kỳ ảnh chụp nhanh nào khi truy vấn bảng. Điều này có thể rất hữu ích nếu bạn muốn chạy các truy vấn lịch sử hoặc tạo lại kết quả của các truy vấn trước đó, có thể là để báo cáo. Du hành thời gian cũng có thể hữu ích khi kiểm tra các thay đổi mã mới vì bạn có thể kiểm tra mã mới bằng truy vấn các kết quả đã biết.
Để xem các ảnh chụp nhanh đã được lưu cho một bảng:
spark-sql> SELECT * FROM my_catalog.my_table.snapshots; 2022-07-25 17:26:47.53 527713811620162549 NULL append s3://iceberg/my_table/metadata/snap-527713811620162549-1-c16452b4-b384-42bc-af07-b2731299e2b8.avro {"added-data-files":"3","added-files-size":"2706","added-records":"3","changed-partition-count":"2","spark.app.id":"local-1658795082601","total-data-files":"3","total-delete-files":"0","total-equality-deletes":"0","total-files-size":"2706","total-position-deletes":"0","total-records":"3"} Time taken: 7.236 seconds, Fetched 1 row(s)
Vài ví dụ:
-- time travel to October 26, 1986 at 01:21:00 spark-sql> SELECT * FROM my_catalog.my_table TIMESTAMP AS OF '1986-10-26 01:21:00'; -- time travel to snapshot with id 10963874102873 spark-sql> SELECT * FROM prod.db.table VERSION AS OF 10963874102873;
Bạn có thể thực hiện các lần đọc gia tăng bằng ảnh chụp nhanh, nhưng bạn phải sử dụng Spark, không phải Spark-SQL. Ví dụ:
scala> spark.read() .format(“iceberg”) .option(“start-snapshot-id”, “10963874102873”) .option(“end-snapshot-id”, “10963874102994”) .load(“s3://iceberg/my_table”)
Bạn cũng có thể khôi phục bảng về một thời điểm hoặc một ảnh chụp nhanh cụ thể, như trong hai ví dụ sau:
spark-sql> CALL my_catalog.system.rollback_to_timestamp('my_table', TIMESTAMP '2022-07-25 12:15:00.000'); spark-sql> CALL my_catalog.system.rollback_to_snapshot('my_table', 527713811620162549);
Iceberg hỗ trợ tất cả các lệnh SQL biểu cảm như xóa, hợp nhất và cập nhật cấp hàng và điều quan trọng nhất cần làm nổi bật là Iceberg hỗ trợ cả chiến lược háo hức và lười biếng. Chúng tôi có thể mã hóa tất cả những thứ chúng tôi cần xóa (ví dụ: GDPR hoặc CCPA,) nhưng không phải viết lại tất cả các tệp dữ liệu đó ngay lập tức, chúng tôi có thể lười biếng thu thập rác khi cần và điều đó thực sự giúp ích cho hiệu quả trên các bảng khổng lồ được hỗ trợ bởi Iceberg.
Ví dụ: bạn có thể xóa tất cả các bản ghi trong bảng khớp với một vị từ cụ thể. Thao tác sau đây sẽ xóa tất cả các hàng khỏi danh mục video:
spark-sql> DELETE FROM my_catalog.my_table WHERE category = 'video';
Ngoài ra, bạn có thể sử dụng CREATE TABLE AS SELECT hoặc REPLACE TABLE AS SELECT để thực hiện việc này:
spark-sql> CREATE TABLE my_catalog.my_table_music AS SELECT * FROM my_catalog.my_table WHERE category = 'music';
Bạn có thể hợp nhất hai bảng rất dễ dàng:
spark-sql> MERGE INTO my_catalog.my_data pt USING (SELECT * FROM my_catalog.my_data_new) st ON pt.id = st.id WHEN NOT MATCHED THEN INSERT *;
Iceberg là nền tảng cho tiêu chuẩn bảng phân tích mở và sử dụng hành vi SQL cũng như trừu tượng hóa bảng thực không giống như các định dạng bảng tổ ong khác và áp dụng các nguyên tắc cơ bản của kho dữ liệu để khắc phục sự cố trước khi chúng tôi biết mình gặp phải. Với kỹ thuật dữ liệu khai báo, chúng ta có thể định cấu hình các bảng và không phải lo lắng về việc thay đổi từng công cụ để phù hợp với nhu cầu của dữ liệu. Điều này mở ra các đề xuất và tối ưu hóa tự động. Với các cam kết an toàn, các dịch vụ dữ liệu có thể giúp tránh con người trông nom khối lượng công việc dữ liệu.
Để kiểm tra lịch sử, ảnh chụp nhanh và siêu dữ liệu khác của bảng, Iceberg hỗ trợ truy vấn siêu dữ liệu. Các bảng siêu dữ liệu được xác định bằng cách thêm tên bảng siêu dữ liệu (ví dụ: lịch sử) sau tên bảng gốc trong truy vấn của bạn.
Để hiển thị các tệp dữ liệu của bảng:
spark-sql> SELECT * FROM my_catalog.my_table.files;
Để hiển thị bảng kê khai:
spark-sql> SELECT * FROM my_catalog.my_table.manifests;
Để hiển thị lịch sử bảng:
spark-sql> SELECT * FROM my_catalog.my_table.history;
Để hiển thị ảnh chụp nhanh:
spark-sql> SELECT * FROM my_catalog.my_table.snapshots;
Bạn cũng có thể tham gia các ảnh chụp nhanh và lịch sử bảng để xem ứng dụng đã viết từng ảnh chụp nhanh:
spark-sql> select h.made_current_at, s.operation, h.snapshot_id, h.is_current_ancestor, s.summary['spark.app.id'] from my_catalog.my_table.history h join my_catalog.my_table.snapshots s on h.snapshot_id = s.snapshot_id order by made_current_at;
Bây giờ bạn đã học những điều cơ bản, hãy tải một số dữ liệu của bạn vào Iceberg, sau đó tìm hiểu thêm từ Khởi động nhanh Spark và Iceberg và Tài liệu về Iceberg .
Apache Iceberg có tích hợp với nhiều công cụ thực thi và truy vấn khác nhau, trong đó các bảng Apache Iceberg có thể được tạo và quản lý bởi các trình kết nối này. Các công cụ hỗ trợ Iceberg là Spark , Flink , Hive , Presto , Trino , Dremio , Snowflake .
Apache Iceberg nhận được nhiều sự chú ý dưới dạng định dạng bảng cho các hồ dữ liệu. Cộng đồng nguồn mở đang phát triển và số lượng tích hợp ngày càng tăng từ nhiều nhà cung cấp đám mây và khung ứng dụng có nghĩa là đã đến lúc phải coi trọng Iceberg, bắt đầu thử nghiệm, học hỏi và lập kế hoạch tích hợp nó vào kiến trúc hồ dữ liệu hiện có. Ghép nối Iceberg với MinIO cho các kho dữ liệu và phân tích đa đám mây.
Khi bạn bắt đầu với Iceberg và MinIO, vui lòng liên hệ và chia sẻ kinh nghiệm của bạn hoặc đặt câu hỏi thông qua kênh Slack của chúng tôi .
Cũng được xuất bản ở đây .