SodaCL kiểm tra kho dữ liệu crawl: freshness, missing và múi giờ
SodaCL kiểm tra kho dữ liệu crawl là việc viết các điều kiện bằng YAML để Soda quét bảng đã nạp vào kho, xem dữ liệu còn mới không, có thiếu giá trị không. Khác với kiểm từng tệp trước khi nạp, ở đây ta canh chính cái bảng mà báo cáo và model đang đọc. ProxyVN chạy Soda Core 3.5.6 trên DuckDB ngày 03/11/2026, quét cùng một bảng ở hai thời điểm khác nhau, và gặp một lỗi múi giờ làm check freshness báo đạt dù dữ liệu đã cũ. Bài ghi lại cấu hình, con số và cách sửa.
SodaCL kiểm tra kho dữ liệu crawl: mục tiêu và phạm vi không lặp
Phần này chốt bài toán, đầu ra và những gì bài không bàn.
Bài toán
Một crawler giá chạy mỗi sáng, nạp kết quả vào bảng crawl_prices trong kho dữ liệu. Báo cáo giá đọc bảng này lúc 9 giờ. Có ngày crawler lỗi, không nạp gì, nhưng báo cáo vẫn chạy và hiển thị giá hôm qua như thể là giá hôm nay. Không ai nhận ra cho tới khi khách hỏi.
Bài toán là phát hiện bảng đã cũ hoặc thiếu dữ liệu, ngay tại kho, trước khi người dùng đọc.
Đầu ra nghiệm thu
Đầu ra gồm tệp YAML chứa các check, và báo cáo freshness của cùng một bảng khi quét ở hai thời điểm: 30 phút sau lần nạp và 30 giờ sau lần nạp. Kết quả hai lần quét phải khác nhau đúng như kỳ vọng. Nếu không khác, cấu hình đang sai ở đâu đó.
Ranh giới với Great Expectations
Great Expectations chấm từng lô dữ liệu trước khi nạp, có báo cáo theo lô. SodaCL ở đây canh bảng sau khi nạp, nhất là độ mới so với thời điểm quét. Hai công cụ có vùng chồng lấn, nhưng bài không dịch lại suite Great Expectations sang SodaCL. Trọng tâm là freshness, missing và cái bẫy thời gian.
Khóa Soda v3
Soda có hai dòng sản phẩm đang song song là v3 và v4, cú pháp và API khác nhau. Bài khóa ở soda-core 3.5.6 với gói soda-core-duckdb cùng phiên bản, đọc tài liệu SodaCL v3. Không trộn ví dụ của v4 vào. Ai dùng v4 nên đọc tài liệu v4 riêng.
Phiên bản đã khóa
Lab dùng soda-core 3.5.6, soda-core-duckdb 3.5.6, duckdb 1.0.0, Python 3.12 trên Windows. Lần cài đầu, import soda báo thiếu module distutils, vì Python 3.12 đã bỏ module này. Cài thêm gói setuptools là chạy được.
Ai nên đọc
Người vận hành kho dữ liệu có bảng nạp từ crawler hằng ngày. Người làm báo cáo cần biết dữ liệu mình đọc còn mới hay không. Người đã thử Soda nhưng thấy check freshness luôn đạt và nghi ngờ điều đó.
Viết SodaCL checks trên bảng đã nạp, theo dõi freshness và missing với SodaCL kiểm tra kho dữ liệu crawl
Trước khi viết check, cần nắm cách Soda nghĩ về một lần quét.
Một lần quét là một câu hỏi tại một thời điểm
Soda kết nối tới nguồn dữ liệu, chạy truy vấn để lấy các chỉ số, rồi so chỉ số với ngưỡng trong check. Kết quả mỗi check là pass, fail, warn hoặc lỗi. Một lần quét gắn với một thời điểm gọi là NOW. Freshness luôn được tính so với NOW.
Missing metrics
Theo trang missing metrics trong tài liệu SodaCL v3, có hai chỉ số chính: missing_count đếm số dòng thiếu, missing_percent tính phần trăm. Mặc định, thiếu nghĩa là NULL. Có thể khai báo thêm giá trị được coi là thiếu bằng missing values.
Với dữ liệu crawl, giá bằng 0 thường là dấu hiệu parser không lấy được giá, không phải sản phẩm miễn phí. Khai báo 0 là giá trị thiếu giúp check phản ánh đúng chất lượng.
Freshness
Theo trang freshness, check freshness lấy giá trị lớn nhất của một cột thời gian, so với NOW, rồi so khoảng cách với ngưỡng như 1d hay 26h. Nếu dòng mới nhất cũ hơn ngưỡng, check trượt.
Điều kiện ngầm là cột thời gian và NOW cùng hệ giờ. Lab sẽ cho thấy chuyện gì xảy ra khi điều kiện này không đúng.
Hai cột thời gian của dữ liệu crawl
Dữ liệu crawl thường có hai mốc. fetched_at là lúc tải trang. ingested_at là lúc nạp vào kho. Hai mốc này có thể lệch nhau vài giờ nếu crawler chạy đêm và lệnh nạp chạy sáng. Mỗi mốc trả lời một câu hỏi khác nhau.
Freshness trên ingested_at cho biết lệnh nạp có chạy không. Freshness trên fetched_at cho biết dữ liệu có phản ánh website gần đây không. Lab đặt check trên cả hai.
Vì sao canh ở kho thay vì ở tệp
Kiểm tệp trước khi nạp không bắt được trường hợp lệnh nạp không chạy. Không có tệp mới thì không có gì để kiểm, và không có cảnh báo nào được gửi. Canh ở kho thì khác: bảng vẫn còn đó, check freshness vẫn chạy, và chính việc thiếu dữ liệu mới làm check trượt. Hai lớp kiểm bổ sung cho nhau.
Tệp cấu hình và tệp check
Soda tách hai tệp. Tệp cấu hình khai báo nguồn dữ liệu và cách kết nối. Tệp check chứa các điều kiện viết bằng SodaCL. Cách tách này cho phép dùng chung tệp check giữa môi trường thử và môi trường thật, chỉ đổi tệp cấu hình.
Không dùng dữ liệu thật trong lab
Lab dựng bảng bằng mã, với URL của một cửa hàng giả. Mục đích là đặt từng lỗi đúng chỗ để biết check có bắt được hay không. Dữ liệu thật sẽ có thêm những lỗi không lường trước, nhưng cách check hoạt động thì giống nhau. Khi đã tin cấu hình, mới trỏ sang bảng thật.
Bảng dữ liệu lab
Bảng crawl_prices có bốn cột: url, price, fetched_at, ingested_at. Bảng chứa hai lô nạp, mỗi lô 100 dòng, nạp lúc 8 giờ 30 sáng ngày 02/11 và 03/11 theo giờ Việt Nam. Lô thứ hai có 4 dòng giá rỗng và 3 dòng giá bằng 0.
Khóa Soda v3 và khai báo data source kiểm thử cho SodaCL kiểm tra kho dữ liệu crawl
Phần này viết tệp cấu hình và tệp check.
Cấu hình nguồn DuckDB
data_source crawl_kho:
type: duckdb
path: kho.duckdb
read_only: true
read_only bằng true để Soda không giữ khóa ghi trên tệp kho. Ở Windows, lab vẫn gặp lỗi khi xóa tệp kho trong lúc tiến trình Soda còn mở kết nối. Lab xử lý bằng cách dùng tệp kho riêng cho mỗi ca.
Tệp check
checks for crawl_prices:
- row_count > 0
- missing_count(price) = 0:
name: Gia khong rong (dem)
- missing_percent(price) < 5:
name: Gia rong duoi 5%
missing values: [0]
- missing_count(url) = 0
- freshness(ingested_at) < 1d:
name: Lo nap moi nhat chua qua 1 ngay
- freshness(fetched_at) < 26h:
name: Trang tai chua qua 26 gio
Một tệp check cho mỗi bảng
Có thể gom check của nhiều bảng vào một tệp, mỗi bảng một khối checks for. Lab chỉ có một bảng. Với kho có nhiều bảng crawl từ nhiều nguồn, nên tách tệp theo nguồn. Khi một nguồn ngừng crawl, chỉ cần bỏ tệp của nó khỏi lịch quét.
Đặt tên check
Mỗi check có thể có trường name. Tên hiện trong báo cáo thay cho biểu thức. Báo cáo gửi cho người không đọc YAML nên dùng tên dễ hiểu. Lab dùng tên không dấu để tránh lỗi bảng mã khi in ra console Windows.
Hai check thiếu giá khác nhau
Check thứ hai đếm dòng giá NULL, ngưỡng bằng 0. Check thứ ba tính phần trăm, coi cả NULL lẫn 0 là thiếu, ngưỡng dưới 5. Lab đặt cả hai để thấy cùng một bảng có thể đạt check này mà trượt check kia.
Gọi quét từ Python
from soda.scan import Scan
s = Scan()
s.set_data_source_name("crawl_kho")
s.add_configuration_yaml_file("config.yml")
s.add_sodacl_yaml_file("checks.yml")
s.add_variables({"NOW": "2026-11-03T09:00:00+07:00"})
code = s.execute()
r = s.get_scan_results()
Biến NOW cho phép đặt thời điểm quét. Trong thực tế, không đặt NOW thì Soda dùng giờ hiện tại. Lab đặt NOW để mô phỏng hai lần quét cách nhau hơn một ngày mà không phải đợi.
Chạy bằng dòng lệnh
Soda còn có lệnh soda scan đọc cùng hai tệp. Lab gọi qua Python vì cần đặt biến NOW và đọc kết quả dạng dict. Với lịch chạy đơn giản, dòng lệnh là đủ. Kết quả và mã thoát tương tự.
Mã thoát
execute trả về mã. Lab ghi nhận 0 khi mọi check đạt, 2 khi có check trượt, 3 khi có lỗi chạy. Đưa mã này vào lịch chạy để biết ngay lần quét có vấn đề mà không cần đọc báo cáo.
Viết missing metrics cùng freshness trên timestamp ingest với SodaCL kiểm tra kho dữ liệu crawl
Phần này đọc kết quả missing và cách Soda dịch check thành SQL.
Một truy vấn cho cả sáu check
Khi bảng không tồn tại, Soda in ra truy vấn đã chạy. Nhờ đó thấy được Soda gom sáu check thành một câu SELECT duy nhất: COUNT(*), đếm price IS NULL, đếm price IS NULL OR price IN (0), đếm url IS NULL, MAX(ingested_at), MAX(fetched_at). Một lần quét chỉ đọc bảng một lần.
Điều này có ích với bảng lớn trong kho tính tiền theo lượng dữ liệu quét. Thêm check trên cùng bảng không làm tăng số lần đọc.
missing values dịch thành điều kiện IN

NULL và 0 đều là thiếu
Khai báo missing values bằng [0] được dịch thành price IS NULL OR price IN (0). Không có phép màu nào. Nếu muốn coi chuỗi rỗng hay chữ N/A là thiếu với cột chữ, cũng khai báo theo cách tương tự.
Kết quả missing
Check |
Giá trị |
Kết quả |
|---|---|---|
missing_count(price) = 0 |
4 |
fail |
missing_percent(price) < 5, coi 0 là thiếu |
3,5 |
pass |
missing_count(url) = 0 |
0 |
pass |
row_count > 0 |
200 |
pass |
Đọc hai check thiếu giá
Có 4 dòng NULL và 3 dòng bằng 0, tổng 7 trên 200 dòng, tức 3,5 phần trăm. Check đếm NULL trượt vì 4 lớn hơn 0. Check phần trăm đạt vì 3,5 nhỏ hơn 5. Cùng một bảng, hai check cho hai kết luận.
Không check nào sai. Chúng trả lời hai câu hỏi khác nhau. Câu đầu là có dòng nào thiếu không. Câu sau là tỷ lệ thiếu có chấp nhận được không. Chọn check nào để chặn báo cáo là quyết định nghiệp vụ.
Phần trăm tính trên cả bảng
missing_percent tính trên toàn bộ 200 dòng của bảng, gồm cả lô hôm qua sạch sẽ. Nếu chỉ nhìn lô hôm nay, tỷ lệ là 7 trên 100, tức 7 phần trăm, vượt ngưỡng. Check trên cả bảng làm loãng lỗi của lô mới.
SodaCL cho phép lọc dữ liệu trong check. Với bảng nhiều lô, nên lọc theo lô mới nhất khi đo tỷ lệ thiếu. Lab chưa thử cú pháp lọc, chỉ ghi nhận hiện tượng.
Thiếu url quan trọng hơn thiếu giá
Lab đặt missing_count(url) bằng 0 không có dung sai. URL là khóa để nối dữ liệu crawl với sản phẩm và để truy lại trang gốc. Một dòng không có URL gần như vô dụng. Giá có thể thiếu vì hết hàng, URL thì không có lý do gì để thiếu.
Bảng sạch
Ca lô sạch dùng cùng cấu trúc nhưng không có giá rỗng hay giá 0. Mọi check missing đều đạt, giá trị 0 và 0,0. Mã thoát là 0. Đây là ca đối chứng cần chạy mỗi khi sửa tệp check.
Chạy scan ở hai thời điểm với cùng dữ liệu bằng SodaCL kiểm tra kho dữ liệu crawl
Phần này là trọng tâm: cùng một bảng, quét ở hai thời điểm, xem freshness thay đổi ra sao.
Kế hoạch
Lần quét thứ nhất đặt NOW bằng 9 giờ sáng 03/11 giờ Việt Nam, 30 phút sau lần nạp cuối. Freshness trên ingested_at phải đạt. Lần quét thứ hai đặt NOW bằng 15 giờ chiều 04/11 giờ Việt Nam, 30 giờ 30 phút sau lần nạp cuối. Freshness phải trượt vì quá một ngày.
Kết quả lần đầu chạy
Cả hai lần quét đều báo freshness đạt. Lần thứ hai, Soda tính độ cũ của ingested_at là 23 giờ 30 phút, dưới ngưỡng một ngày, nên đạt. Theo đồng hồ thật, dữ liệu đã cũ 30 giờ 30 phút.
Lần quét thứ nhất còn lạ hơn: freshness mang giá trị âm, hiển thị là trừ một ngày cộng 17 giờ 30 phút. Dữ liệu được coi là đến từ tương lai.
Đọc phần diagnostics

Diagnostics lệch 7 tiếng
Kết quả mỗi check freshness có phần diagnostics với các trường maxColumnTimestamp, maxColumnTimestampUtc, nowTimestamp và nowTimestampUtc. Lần quét đầu cho thấy:
maxColumnTimestampUtc: 2026-11-03 08:30:00+00:00
nowTimestampUtc: 2026-11-03 02:00:00+00:00
freshness: -1 day, 17:30:00
NOW được chuyển đúng từ 9 giờ giờ Việt Nam sang 2 giờ UTC. Nhưng 8 giờ 30 trong cột ingested_at bị coi là 8 giờ 30 UTC, trong khi nó thật ra là giờ Việt Nam.
Nguyên nhân
Cột ingested_at kiểu TIMESTAMP không kèm múi giờ. Lệnh nạp ghi giờ địa phương vào đó. Soda đọc giá trị không có múi giờ và coi là UTC. Kết quả là mọi mốc trong bảng bị đẩy lên 7 tiếng so với thực tế.
Hệ quả: check freshness luôn có thêm 7 tiếng ân hạn. Ngưỡng một ngày thực chất là 31 tiếng. Dữ liệu cũ hơn một ngày vẫn qua kiểm tra.
Sửa bằng cách lưu giờ UTC

Lưu giờ UTC
Lab dựng lại bảng, ghi ingested_at bằng giờ UTC: 1 giờ 30 thay cho 8 giờ 30. Chạy lại hai lần quét với cùng NOW. Lần thứ nhất cho freshness 30 phút, đạt. Lần thứ hai cho 1 ngày 6 giờ 30 phút, trượt.
Ca |
NOW (giờ VN) |
Freshness ingested_at |
Kết quả |
|---|---|---|---|
Giờ VN không múi giờ |
03/11 09:00 |
âm 6 giờ 30 phút |
pass |
Giờ VN không múi giờ |
04/11 15:00 |
23 giờ 30 phút |
pass |
Giờ UTC |
03/11 09:00 |
30 phút |
pass |
Giờ UTC |
04/11 15:00 |
1 ngày 6 giờ 30 phút |
fail |
Vì sao lỗi này khó thấy
Lỗi múi giờ không làm check nào trượt. Ngược lại, nó làm check dễ đạt hơn. Không ai đi tìm lỗi khi mọi thứ xanh. Lỗi chỉ lộ ra khi có sự cố thật: crawler ngừng chạy một ngày mà không ai được báo. Phép thử hai thời điểm là cách rẻ nhất để phát hiện sớm.
Check fetched_at cũng bị ảnh hưởng
Check freshness trên fetched_at với ngưỡng 26 giờ cho cùng hiện tượng. Với giờ Việt Nam không múi giờ, lần quét thứ hai tính 1 ngày 1 phút, dưới 26 giờ, đạt. Với giờ UTC, tính 1 ngày 7 giờ 1 phút, trượt. Mọi cột thời gian trong bảng cần cùng quy ước.
Giá trị âm là tín hiệu
Freshness âm nghĩa là dòng mới nhất nằm sau thời điểm quét. Trừ khi đồng hồ máy lệch, đây gần như luôn là lỗi múi giờ. Nên thêm bước kiểm: nếu freshness âm, báo lỗi cấu hình thay vì coi là đạt.
Đọc freshness so với now và phân biệt dataset trễ với timestamp sai trong SodaCL kiểm tra kho dữ liệu crawl
Phần này giúp đọc một kết quả freshness và quyết định lỗi nằm ở đâu.
Ba khả năng khi freshness trượt
Khả năng thứ nhất: lệnh nạp không chạy, bảng thật sự cũ. Khả năng thứ hai: lệnh nạp có chạy nhưng không có dòng mới, ví dụ crawler trả về rỗng. Khả năng thứ ba: dữ liệu mới có nhưng cột thời gian ghi sai, ví dụ ghi giờ tải gốc từ hôm trước.
Check row_count giúp tách khả năng thứ hai. Nếu số dòng không tăng sau lần nạp, crawler đã trả về rỗng.
Ba khả năng khi freshness đạt mà nghi ngờ
Khả năng thứ nhất: dữ liệu mới thật. Khả năng thứ hai: cột thời gian bị lệch múi giờ như lab. Khả năng thứ ba: lệnh nạp ghi thời gian nạp nhưng nạp lại dữ liệu cũ, ví dụ chạy lại một tệp từ tuần trước.
Khả năng thứ ba nguy hiểm vì ingested_at mới, mọi check freshness trên cột này đều đạt. Chỉ freshness trên fetched_at mới bắt được. Đây là lý do nên đặt check trên cả hai cột.
Đọc diagnostics thay vì chỉ đọc pass hay fail
Diagnostics cho biết giá trị lớn nhất của cột và NOW, cả bản gốc lẫn bản UTC. Chỉ cần nhìn hai dòng UTC là biết Soda đang hiểu thời gian thế nào. Nếu maxColumnTimestampUtc trùng giờ địa phương bạn ghi, cột đó đang bị đọc sai.
Máy chủ kho đặt giờ nào
Một số kho dữ liệu lấy giờ hiện tại theo múi giờ của phiên kết nối. Nếu lệnh nạp ghi ingested_at bằng hàm now của kho, giá trị phụ thuộc cấu hình phiên. Cùng một câu lệnh chạy từ máy ở Việt Nam và từ máy chủ đặt UTC có thể ghi hai giá trị lệch 7 tiếng. Nên ghi giờ UTC tường minh từ ứng dụng nạp.
Dùng kiểu có múi giờ
Cách chắc hơn ghi UTC bằng tay là dùng kiểu cột có múi giờ, ví dụ TIMESTAMPTZ trong DuckDB hay timestamp with time zone trong PostgreSQL. Lab chưa thử kiểu này với Soda, nên chưa khẳng định Soda đọc đúng. Ai đổi sang kiểu có múi giờ nên chạy lại phép thử hai thời điểm để xác nhận.
Đồng hồ máy chạy Soda
NOW mặc định lấy từ đồng hồ máy chạy Soda. Máy ảo lâu ngày không đồng bộ giờ có thể lệch vài phút, hiếm khi tới vài tiếng. Lỗi múi giờ trong lab lớn hơn nhiều, nhưng khi ngưỡng freshness sát, độ lệch đồng hồ cũng đáng kiểm. Bật đồng bộ thời gian trên máy chạy lịch quét là việc nên làm một lần.
Ngưỡng nên lấy từ lịch chạy
Ngưỡng freshness nên bằng chu kỳ nạp cộng một khoảng dư. Crawler chạy mỗi ngày lúc 8 giờ thì ngưỡng 26 giờ cho phép trễ hai tiếng. Ngưỡng một ngày đúng bằng chu kỳ sẽ trượt mỗi khi lệnh nạp chậm vài phút.
Quét vào thời điểm nào
Quét ngay sau lần nạp chỉ kiểm được lệnh nạp vừa chạy. Quét ngay trước giờ báo cáo đọc dữ liệu mới bảo vệ người đọc. Lab mô phỏng cả hai. Trong thực tế, nên quét ngay trước khi báo cáo chạy, và cho báo cáo dừng nếu mã thoát khác 0.
Cảnh báo trước khi trượt
SodaCL v3 cho đặt hai mức warn và fail trong cùng một check. Có thể cảnh báo khi freshness vượt 25 giờ và chặn khi vượt 30 giờ. Mức cảnh báo cho người vận hành thời gian xử lý trước khi báo cáo bị chặn. Lab chưa thử cú pháp này, chỉ dùng một ngưỡng.
Bảng không tồn tại
Ca cuối quét một tệp kho rỗng, không có bảng crawl_prices. Soda báo Catalog Error, in ra truy vấn, mã thoát 3. Không có check nào ra pass hay fail. Đây là lỗi hạ tầng, khác với dữ liệu cũ. Lịch chạy nên xử lý mã 3 khác mã 2.
Đầu ra nghiệm thu: YAML scan và báo cáo freshness theo hai thời điểm ingest của SodaCL kiểm tra kho dữ liệu crawl
Phần cuối gom kết quả thành bộ bàn giao.
Bộ bàn giao
Bộ bàn giao gồm tệp cấu hình, tệp check, tệp lab.py dựng bảng và chạy năm lần quét, tệp JSON kết quả quét giờ UTC lúc 30 phút sau nạp. Người nhận chạy lại lab.py và phải thấy đúng bảng bốn ca freshness ở trên.
Tiêu chí đạt
Hai lần quét cách nhau hơn một ngày cho hai kết quả freshness khác nhau. Không có freshness âm. Check missing phân biệt được NULL và giá 0. Lỗi bảng không tồn tại ra mã 3, không lẫn với dữ liệu trượt.
Quy trình đề xuất
Bước một, thống nhất mọi cột thời gian lưu UTC hoặc có múi giờ. Bước hai, đặt check freshness trên cả ingested_at và fetched_at với ngưỡng theo lịch chạy. Bước ba, quét trước giờ báo cáo, chặn báo cáo khi mã khác 0. Bước bốn, khi có freshness âm, xử lý như lỗi cấu hình.
Khi nào cần proxy với SodaCL kiểm tra kho dữ liệu crawl
Soda quét kho dữ liệu, không tải trang web, nên bản thân việc quét không cần proxy. Nếu kho nằm trên dịch vụ đám mây và mạng công ty bắt đi qua proxy, đó là cấu hình mạng của tiến trình Soda, không liên quan tới dữ liệu.
Proxy liên quan tới bước crawl trước đó. Freshness trên fetched_at trượt nhiều ngày liền có thể do crawler bị chặn và không lấy được trang mới. Với website được phép thu thập nhưng hiển thị khác theo vùng, có lúc cần IP tại Việt Nam. Khi đó anh em có thể mua proxy tĩnh Việt Nam tại trang chủ ProxyVN. Proxy không sửa lỗi múi giờ và không làm bảng mới hơn nếu lệnh nạp không chạy. Vai trò hợp lệ của proxy được giải thích ở bài Web Scraping proxy là gì.
Giờ của máy crawler
Crawler chạy qua proxy ở vùng khác vẫn nên ghi fetched_at theo đồng hồ máy chạy crawler, quy về UTC. Đừng lấy giờ từ header Date của trang trả về, vì header này có thể do máy chủ cache tạo ra và không phản ánh lúc bạn tải. Cấu hình proxy cho crawler theo đúng định dạng có trong bài định dạng proxy.
Lưu kết quả quét
Kết quả quét dạng dict có thể ghi ra JSON như lab làm, rồi nạp lại vào kho để theo dõi theo thời gian. Bảng lịch sử quét cho biết freshness trung bình mỗi ngày, ngày nào lệnh nạp trễ, tỷ lệ thiếu giá có xu hướng tăng không. Những con số này hữu ích hơn một lần pass hay fail riêng lẻ.
Những gì lab chưa thử
Lab chưa thử Soda Cloud, chưa thử check có lọc theo lô, chưa thử kiểu cột TIMESTAMPTZ, chưa thử nguồn dữ liệu khác DuckDB như PostgreSQL hay BigQuery. Cách mỗi adapter xử lý cột thời gian không múi giờ có thể khác nhau. Lab cũng chưa thử Soda v4.
Checklist SodaCL kiểm tra kho dữ liệu crawl

Checklist
- Khóa phiên bản Soda v3 hoặc v4, không trộn tài liệu.
- Cài setuptools nếu dùng Python 3.12 với soda-core 3.5.6.
- Mọi cột thời gian lưu UTC hoặc có múi giờ.
- Freshness đặt trên cả ingested_at và fetched_at.
- Ngưỡng freshness bằng chu kỳ nạp cộng khoảng dư.
- missing values khai báo giá 0 là thiếu nếu đúng nghiệp vụ.
- Đọc diagnostics UTC, coi freshness âm là lỗi.
- Xử lý mã thoát 2 và 3 khác nhau.
Câu hỏi thường gặp về SodaCL kiểm tra kho dữ liệu crawl
Freshness trong Soda tính thế nào?
Lấy giá trị lớn nhất của cột thời gian, so với NOW của lần quét, rồi so khoảng cách với ngưỡng.
Vì sao check freshness luôn đạt?
Thường do cột thời gian lưu giờ địa phương không kèm múi giờ. Lab cho thấy Soda coi giá trị đó là UTC, làm dữ liệu trẻ ra 7 tiếng.
missing_count và missing_percent khác gì?
missing_count đếm số dòng thiếu, missing_percent tính tỷ lệ. Lab có 4 dòng NULL làm missing_count trượt, trong khi tỷ lệ 3,5 phần trăm vẫn đạt.
Có coi giá 0 là thiếu được không?
Được. Khai báo missing values bằng [0], Soda dịch thành điều kiện price IS NULL OR price IN (0).
Mã thoát của Soda nghĩa là gì?
Lab ghi nhận 0 khi mọi check đạt, 2 khi có check trượt, 3 khi lần quét gặp lỗi như bảng không tồn tại.
Quét kho có cần proxy không?
Không. Chỉ bước crawl hoặc kết nối tới kho qua mạng công ty mới có thể cần.
SodaCL kiểm tra kho dữ liệu crawl và những điều cần nhớ
SodaCL kiểm tra kho dữ liệu crawl chỉ đáng tin khi cột thời gian và thời điểm quét cùng hệ giờ. Lab trên Soda Core 3.5.6 cho thấy giờ Việt Nam lưu không kèm múi giờ làm check freshness một ngày thành 31 tiếng, dữ liệu cũ 30 giờ vẫn đạt. Chuyển sang UTC, cùng hai lần quét cho đúng kết quả đạt rồi trượt. Đặt freshness trên cả giờ tải lẫn giờ nạp, và đọc diagnostics thay vì chỉ nhìn chữ pass. Cần IP tĩnh cho bước crawl trước khi SodaCL kiểm tra kho dữ liệu crawl, liên hệ Proxy.vn - Nhà cung cấp dịch vụ proxy chất lượng hàng đầu Việt Nam.