Trino SQL Bài học 40: Thao tác dữ liệu (INSERT, UPDATE, DELETE) trong Data Lake
Mục tiêu bài học:
-
Xóa bỏ tư duy thao tác dữ liệu (DML) của hệ quản trị CSDL truyền thống (OLTP) khi làm việc với Big Data.
-
Hiểu rõ sự phụ thuộc sống còn của các lệnh
INSERT,UPDATE,DELETEvào loại Connector và Table Format (Iceberg, Delta Lake). -
Cú pháp chuẩn để thêm, sửa, xóa dữ liệu trên Trino.
-
Nắm vững triết lý "Bất biến" (Immutable) và chi phí tiềm ẩn khổng lồ của việc Update/Delete từng dòng trên Data Lake.
1. Sự thật phũ phàng về DML trong Data Lake
Nếu bạn xuất thân từ nền tảng MySQL hay SQL Server, việc chạy lệnh UPDATE hay DELETE một vài dòng dữ liệu diễn ra trong chớp mắt. Nhưng trên Data Lake (như Amazon S3, HDFS), dữ liệu được lưu dưới dạng các tệp tin vật lý khổng lồ (Parquet, ORC). Các hệ thống lưu trữ này có bản chất là Bất biến (Immutable) - Ghi một lần, không thể sửa giữa chừng.
Và hãy nhớ nguyên lý tối thượng: Trino chỉ là một Engine tính toán, nó không lưu trữ dữ liệu. Việc bạn có thể chạy được lệnh UPDATE/DELETE hay không hoàn toàn phụ thuộc vào Connector (Cầu nối) mà bạn đang dùng:
-
Nếu bạn nối Trino với cơ sở dữ liệu truyền thống (PostgreSQL Connector, MySQL Connector): Các lệnh DML hoạt động bình thường.
-
Nếu bạn nối Trino với Data Lake sử dụng Hive Connector (bảng CSV, JSON thông thường): Lệnh
UPDATEvàDELETEsẽ bị Trino báo lỗi ngay lập tức: "This connector does not support modifies". -
Nếu bạn sử dụng các Table Format hiện đại (Apache Iceberg, Delta Lake, Apache Hudi): Trino hỗ trợ đẩy đủ
INSERT,UPDATE,DELETE.
2. INSERT: Đổ thêm dữ liệu (Append)
Đây là thao tác "thuận tự nhiên" nhất của Data Lake. Việc thêm dữ liệu thực chất chỉ là tạo ra một file Parquet mới và đặt vào thư mục của bảng.
Cách 1: Chèn dữ liệu thủ công (Ít dùng trong thực tế)
SQL
INSERT INTO iceberg.sales.orders (orderkey, custkey, orderstatus, totalprice)
VALUES
(1001, 50, 'O', 150000.0),
(1002, 51, 'F', 200000.0);
Cách 2: Chèn dữ liệu từ kết quả truy vấn (ETL / ELT - Rất phổ biến) Kỹ thuật này lấy dữ liệu từ một bảng/nguồn khác, biến đổi (Transform) và đổ vào bảng đích.
SQL
INSERT INTO iceberg.sales.high_value_orders (orderkey, custkey, totalprice)
SELECT
orderkey,
custkey,
totalprice
FROM tpch.tiny.orders
WHERE totalprice > 200000;
3. DELETE: Xóa dữ liệu (Row-level Deletion)
Lệnh DELETE cho phép bạn xóa các dòng cụ thể thỏa mãn điều kiện.
SQL
-- Xóa các đơn hàng bị hủy (Status = 'C')
DELETE FROM iceberg.sales.orders
WHERE orderstatus = 'C';
Góc nhìn Kỹ sư: Chuyện gì xảy ra dưới nền? Trong các Table Format như Iceberg, khi bạn DELETE 1 dòng, hệ thống không vào file Parquet gốc để xóa. Nó sẽ sử dụng cơ chế Merge-on-Read (Tạo ra một file phụ chứa ID của dòng bị xóa, khi đọc dữ liệu Trino sẽ tự trừ đi) hoặc Copy-on-Write (Đọc toàn bộ file Parquet 100MB lên RAM, loại bỏ 1 dòng đó, rồi ghi lại thành một file Parquet 100MB mới). Hậu quả: Nếu bạn liên tục DELETE từng dòng lắt nhắt, Data Lake của bạn sẽ rác hóa với hàng triệu file nhỏ, làm chậm toàn bộ hệ thống.
4. UPDATE: Cập nhật dữ liệu (Row-level Updates)
Lệnh UPDATE dùng để sửa đổi giá trị của các cột hiện có.
SQL
-- Cập nhật trạng thái đơn hàng và giảm giá cho khách VIP
UPDATE iceberg.sales.orders
SET
orderstatus = 'F',
totalprice = totalprice * 0.9
WHERE custkey = 101 AND orderstatus = 'O';
Chi phí khủng khiếp của UPDATE: Bản chất của UPDATE trên Data Lake chính là một lệnh DELETE cộng với một lệnh INSERT. Nó mang đầy đủ nhược điểm hiệu năng của lệnh xóa lắt nhắt nêu trên. Trino phải định vị file cũ, vô hiệu hóa nó, và ghi file mới.
5. Best Practice: Triết lý "Append-Only" (Chỉ chèn thêm)
Để hệ thống Big Data chạy mượt mà, các chuyên gia Data Engineer thường tránh dùng UPDATE và DELETE trực tiếp. Thay vào đó, họ thiết kế hệ thống theo chuẩn Append-Only.
Cách làm: Thay vì sửa dòng cũ, khi trạng thái đơn hàng thay đổi, hệ thống sẽ INSERT thêm một dòng mới hoàn toàn với cùng orderkey nhưng có updated_at mới hơn.
| order_key | status | updated_at (Timestamp) |
|---|---|---|
| 1001 | O | 2026-10-10 08:00:00 |
| 1001 | F | 2026-10-11 10:00:00 |
Trích xuất dữ liệu mới nhất bằng Window Function: Khi Analyst cần xem báo cáo, họ sẽ dùng kỹ thuật lọc trùng (Bài 27 - ROW_NUMBER) để chỉ lấy dòng có trạng thái mới nhất, bỏ qua các dòng lịch sử.
SQL
WITH latest_orders AS (
SELECT
orderkey,
status,
ROW_NUMBER() OVER (PARTITION BY orderkey ORDER BY updated_at DESC) AS rn
FROM raw_append_only_orders
)
SELECT * FROM latest_orders WHERE rn = 1;
Cách này giúp Data Lake không bao giờ phải sửa file, tốc độ ghi (Ingestion) đạt mức tối đa, và bạn còn lưu lại được toàn bộ lịch sử biến động của dữ liệu.
All rights reserved