GIS 7 — Dữ liệu không gian quy mô lớn & Cloud

13 thg 7, 2026 3 lượt xem
#spark
#big-data
#bigquery
#cloud
#gis

GIS 7 — Dữ liệu không gian quy mô lớn & Cloud

Cả series đến giờ xoay quanh một cỗ máy: PostGIS trên một Postgres đơn. Với ranh giới 63 tỉnh, vài nghìn ATM, vài trăm nghìn khách gắn toạ độ — nó thừa sức và là công cụ đúng. Nhưng có một điểm gãy: khi dữ liệu không gian phình lên hàng trăm triệu đến hàng tỉ dòng, một ST_DWithin hay một spatial join thô trên PostGIS bắt đầu chạy hàng giờ, ngốn hết RAM, rồi timeout. Bài này về những gì xảy ra sau điểm gãy đó: đưa phân tích không gian lên warehouse đám mâySpark phân tán, và một ý tưởng then chốt — lưới phân cấp (H3, S2, geohash) — biến bài toán spatial join đắt đỏ thành một GROUP BY rẻ tiền.

Vì sao cần big-data không gian

Không phải cứ có toạ độ là cần big-data. Ba loại dữ liệu điển hình đẩy bạn qua điểm gãy:

  • Điểm sự kiện khối lượng cực lớn. Mỗi giao dịch thẻ, mỗi lần rút ATM, mỗi phiên đăng nhập app đều có thể mang toạ độ (POS, ATM, GPS điện thoại). Một ngân hàng bán lẻ tạo hàng trăm triệu bản ghi mỗi tháng; nhân vài năm lịch sử là hàng tỉ điểm — vượt xa vùng thoải mái của một Postgres đơn.
  • Log vị trí / GPS liên tục. Fleet giao vận, luồng di chuyển khách, telemetry thiết bị: dòng điểm chảy vào không ngừng, câu hỏi thường là "gom mật độ theo vùng theo thời gian".
  • Raster / ảnh vệ tinh. Ảnh vệ tinh, mô hình độ cao, bản đồ sử dụng đất là lưới pixel khổng lồ — mỗi cảnh hàng trăm MB đến GB. PostGIS có phần raster nhưng không phải chỗ xử lý hàng terabyte ảnh; đó là địa hạt của công cụ phân tán và định dạng cloud-native.

Điểm chung: dữ liệu vừa lớn theo dòng vừa cần phân tích hàng loạt (batch analytics) chứ không phải tra cứu giao dịch từng bản ghi. Đó chính là ranh giới giữa "cơ sở dữ liệu vận hành" và "kho phân tích".

GIS trên warehouse đám mây

Warehouse đám mây (BigQuery, Snowflake, Redshift) là các động cơ SQL cột, phân tán, tách compute–storage, quét hàng tỉ dòng bằng cách rải việc lên hàng trăm node. Nhiều warehouse nay có sẵn kiểu dữ liệu địa lý và hàm không gian, nên bạn phân tích không gian bằng chính SQL mà không phải bê dữ liệu đi đâu.

  • BigQuery GIS (xem tổng quan BigQuery) có kiểu GEOGRAPHY (hình học trên mặt cầu Trái Đất, không phải mặt phẳng) và bộ hàm ST_* quen thuộc: ST_GeogPoint, ST_Distance, ST_DWithin, ST_Contains, ST_Area... Cú pháp gần PostGIS nên chuyển sang khá tự nhiên, khác biệt lớn nhất là quy mô: một ST_DWithin gom điểm quanh mỗi ATM có thể quét tỉ điểm mà vẫn trả trong vài chục giây, vì BigQuery rải việc tự động.
  • Snowflake GeospatialGEOGRAPHY/GEOMETRY cùng bộ ST_* tương tự; hợp khi kho dữ liệu đã đứng trên Snowflake. Amazon Redshift cũng có kiểu GEOMETRY và hàm không gian trong hệ sinh thái AWS.
-- MINH HOẠ (BigQuery GIS — phương ngữ khác, KHÔNG chạy trên sandbox)
-- Đếm giao dịch thẻ trong bán kính 500m quanh mỗi ATM, trên hàng tỉ dòng
SELECT a.atm_id,
       COUNT(*) AS txn_near
FROM `bank.card_txn` t
JOIN `bank.atm` a
  ON ST_DWithin(t.geo, a.geo, 500)   -- geo kiểu GEOGRAPHY, đơn vị mét
GROUP BY a.atm_id;

Ưu điểm lớn: không cần dựng hạ tầng GIS riêng — dữ liệu đã nằm trong warehouse, chỉ thêm cột GEOGRAPHY và viết SQL. Nhược điểm: bộ hàm hẹp hơn PostGIS (thiếu nhiều hàm topology chuyên sâu), và tính tiền theo lượng quét khiến một spatial join thô thiếu chỉ mục có thể đắt bất ngờ — dẫn thẳng tới lý do cần lưới H3 bên dưới.

GIS phân tán với Spark: Apache Sedona

Khi cần xử lý (transform, ETL, ML) khối không gian lớn chứ không chỉ truy vấn SQL, công cụ tự nhiên là Spark (xem tổng quan Spark) — động cơ tính toán phân tán trên nhiều máy. Spark thuần không hiểu hình học; phần bù là Apache Sedona (tên cũ GeoSpark):

  • Thêm kiểu hình học và hàm ST_* vào Spark SQL / DataFrame, để bạn viết spatial join, ST_Contains, ST_Distance trên dữ liệu trải khắp cụm.
  • Cốt lõi là spatial join phân tán có chỉ mục: Sedona phân vùng dữ liệu theo không gian (các điểm gần nhau về cùng một partition) rồi xây spatial index (R-tree/quad-tree) trong từng partition. Nhờ đó join "điểm nằm trong đa giác nào" chạy song song thay vì so mọi điểm với mọi đa giác — khác biệt giữa phútngày.
  • Xử lý được raster / ảnh ở quy mô cụm, hợp cho pipeline ảnh vệ tinh.

Chọn Sedona khi công việc là ETL không gian nặng (gán tỉnh/ô cho hàng tỉ điểm, làm sạch, chuẩn hoá, nạp ngược vào lakehouse) hoặc khi đã có sẵn nền Spark. Chọn warehouse GIS khi công việc thiên về truy vấn phân tích SQL trên dữ liệu đã ở kho.

Hệ thống chỉ mục không gian quy mô: lưới phân cấp

Đây là ý tưởng quan trọng nhất của bài. Spatial join thô — "mỗi điểm nằm trong đa giác nào?", "hai điểm nào gần nhau?" — là phép toán hình học đắt: phải so hình dạng với hình dạng. Ở quy mô tỉ điểm, kể cả có index, nó vẫn nặng. Mẹo của giới big-data không gian: rời khỏi hình học, chuyển sang lưới ô rời rạc.

Lưới phân cấp phủ Trái Đất bằng các ô (cell) có định danh chuỗi/số, ở nhiều mức phân giải lồng nhau. Gán mỗi toạ độ về ID ô chứa nó — đó chỉ là một phép tính, không phải join. Sau khi mọi điểm có cell_id, mọi bài toán không gian biến thành thao tác trên khoá thường:

  • "Gom giao dịch theo vùng" → GROUP BY cell_id (thay cho spatial join với ranh giới).
  • "Hai tập điểm nào ở cùng chỗ" → join theo cell_id (equi-join, cực nhanh, có thể phân tán và cache).
  • "Điểm lân cận" → lấy các ô kề (ring) quanh một ô — thao tác trên ID, không phải hình học.

Các họ lưới phổ biến:

LướiHình ôĐặc điểmTác giả
Uber H3Lục giác (hexagon)Khoảng cách tâm-tâm giữa các ô kề đều nhau (lục giác không có góc chéo như ô vuông) → rất hợp gom mật độ, phân tích lân cận, MLUber
Google S2Ô vuông cong (trên mặt cầu)Phủ mặt cầu bằng đường cong Hilbert, phân cấp mịn, mạnh cho phạm vi (range) và bao phủ vùngGoogle
GeohashÔ chữ nhậtMã hoá lat/lng thành chuỗi base32; tiền tố chung = gần nhau → dễ lọc/nhóm bằng LIKE 'prefix%'Niemeyer
QuadkeyÔ vuông (tile)Chỉ số tile của bản đồ web theo mức zoom; gắn liền tiling để phục vụ bản đồMicrosoft

H3 được ưa dùng trong phân tích vì hình lục giác: mọi ô kề cách tâm đều nhau nên các phép "vùng lân cận", "bán kính k vòng" hành xử đẹp, ít méo hơn lưới vuông. Tinh thần chung của cả bốn: giảm spatial join thành group-by/equi-join — đổi độ chính xác hình học lấy tốc độ và khả năng mở rộng khổng lồ.

Định dạng cloud-native

Song song với động cơ tính toán, big-data không gian có định dạng file riêng tối ưu cho lưu trữ đối tượng (S3/GCS) và đọc song song (nối tiếp định dạng dữ liệu):

  • GeoParquet. Parquet — định dạng cột nén — bổ sung chuẩn lưu hình học (thường mã hoá WKB) kèm metadata. Kế thừa mọi ưu điểm Parquet: nén tốt, đọc theo cột, predicate pushdown, đọc song song trên cụm; là "đơn vị lưu" tự nhiên của lakehouse không gian.
  • Cloud-Optimized GeoTIFF (COG). GeoTIFF (ảnh raster có toạ độ) được tổ chức lại để client đọc từng phần qua HTTP range request — chỉ tải đúng ô/độ phân giải cần, không phải cả file. Nền cho phục vụ ảnh vệ tinh trực tiếp từ object storage.
  • Zarr. Mảng nhiều chiều dạng chunk, hợp raster/khoa học lớn (khí hậu, chuỗi ảnh theo thời gian), đọc song song từng chunk.

Điểm chung: chia nhỏ + đọc chọn lọc từ object storage, để nhiều node xử lý song song mà không tải nguyên khối.

Kiến trúc: lakehouse không gian & tiling

Ghép lại thành một kiến trúc điển hình:

Hai nhánh cuối phản ánh hai mục đích: phân tích (gom theo ô, mô hình rủi ro/gian lận theo địa bàn) và phục vụ bản đồ. Với bản đồ, dữ liệu được tiling — cắt thành ô theo mức zoom (vector tiles / quadkey) để web map chỉ tải phần đang nhìn, đúng ý tưởng level of detail đã bàn ở trực quan hoá.

Đánh đổi: PostGIS vs warehouse/Spark

Không có "cái tốt hơn" — có "cái đúng cho quy mô và mục đích":

Tiêu chíPostGIS (Postgres đơn)Warehouse GIS / Spark + Sedona
Quy môTriệu–chục triệu hình họcTrăm triệu–tỉ+
Kiểu tảiGiao dịch, tra cứu, cập nhậtPhân tích hàng loạt (batch), quét lớn
Độ chính xác hình họcCao — bộ hàm topology đầy đủHàm hẹp hơn; lưới H3 = xấp xỉ
Độ trễ ghi/cập nhậtThấp (OLTP thật)Cao — append/batch, không hợp update lẻ
Vận hànhMột server, đơn giảnHạ tầng phân tán / dịch vụ đám mây
Chi phíCố định, dễ đoánTheo lượng quét/compute — dễ đắt nếu ẩu

Quy tắc thực dụng: giữ dữ liệu vận hành và truy vấn không gian chính xác, vừa phải trên PostGIS; đẩy phân tích quy mô tỉ dòng sang warehouse/Spark, và ở đó luôn ưu tiên lưới H3/S2 thay cho spatial join thô.

Mẹo hiệu năng

  • Index bằng lưới, không join hình học thô. Trước khi viết một spatial join tỉ-dòng, hỏi: "gán mỗi điểm về ô H3 rồi GROUP BY được không?". Thường là được, và nhanh hơn bậc độ lớn.
  • Phân vùng theo ô. Lưu GeoParquet partition theo cell_id (hoặc tiền tố geohash); join/quét chỉ chạm partition liên quan (partition pruning), giảm mạnh lượng đọc.
  • Chọn đúng mức phân giải. Ô quá mịn → nhiều ô, group-by nặng; quá thô → mất chi tiết. Thử vài mức H3 theo bài toán.
  • Cẩn thận chi phí quét trên warehouse. Lọc thời gian/partition trước, tránh ST_* trên toàn bảng — join thô thiếu chỉ mục có thể quét cả kho và tính tiền tương ứng.

Analogy trên sandbox: "gom theo địa bàn"

Bản chất của H3 chỉ là: thay toạ độ liên tục bằng một khoá rời rạc, rồi GROUP BY khoá đó. Sandbox không có toạ độ/H3, nhưng có thể mô phỏng đúng tinh thần bằng cách coi cột city như "ô lưới thô nhất" — gom giao dịch theo địa bàn thành một câu SQL Postgres thuần chạy được thật:

-- ▶ Chạy được
SELECT c.city,
       COUNT(t.id)                       AS num_txn,
       ROUND(SUM(t.amount)::numeric, 2)   AS total_amount,
       ROUND(AVG(t.amount)::numeric, 2)   AS avg_amount
FROM transactions t
JOIN accounts  a ON a.id = t.account_id
JOIN customers c ON c.id = a.customer_id
GROUP BY c.city
ORDER BY total_amount DESC;

Đây chính là hình mẫu thu nhỏ của phân tích H3: nếu city được thay bằng cell_id sinh từ toạ độ, và transactions có tỉ dòng chạy trên BigQuery/Spark thay vì Postgres, thì cấu trúc truy vấn không đổi — vẫn là "gán về ô, rồi gom theo ô". Toàn bộ chương này chỉ là câu SQL trên, phóng đại lên nghìn tỉ dòng và trải khắp một cụm.

Lưu ý sandbox: sandbox là PostgreSQL thuần, không PostGIS, không H3. Chỉ câu GROUP BY c.city ở trên chạy thật (chỉ đụng transactions/accounts/customers). Mọi đoạn BigQuery GIS, Snowflake, Spark/Sedona, hàm h3_* / ST_* trong bài là minh hoạ phương ngữ khác, không đánh dấu chạy được.

Use case thực tế

Bối cảnh NCB — phân tích ~400 triệu giao dịch thẻ/năm theo vị trí, gom bằng H3.

Rủi ro & Marketing muốn hai thứ trên toàn bộ giao dịch thẻ có toạ độ POS: (1) bản đồ mật độ chi tiêu theo địa bàn đô thị để đặt/di dời ATM và ưu đãi merchant; (2) tín hiệu gian lận theo địa bàn — ô nào bất thường về mật độ giao dịch từ chối. Dữ liệu ~400 triệu dòng/năm, vài năm lịch sử — một ST_DWithin thô trên PostGIS chạy hàng giờ và không kịp làm hằng đêm.

Các bước đội Data triển khai:

  1. Đổ vào lakehouse. Giao dịch thẻ (kèm lat/lng của POS) được nạp dạng GeoParquet trên object storage, partition theo ngày.
  2. Gán ô H3 bằng Spark + Sedona. Batch đêm tính cell_id = h3(lat, lng, res=9) cho mọi dòng (một phép tính, không spatial join), ghi lại GeoParquet partition thêm theo tiền tố ô — biến bài toán không gian thành khoá thường.
  3. Gom theo ô = group-by. GROUP BY cell_id, ngày cho ra num_txn, total_amount, decline_rate mỗi ô mỗi ngày — vài phút trên cụm thay vì hàng giờ. Đây đúng là câu SQL sandbox ở trên, chỉ thay city bằng cell_id và chạy phân tán.
  4. Phát hiện bất thường theo ô. So decline_rate mỗi ô với nền lịch sử của các ô lân cận (ring H3) để gắn cờ cụm nghi vấn — nối vào giám sát giao dịch của AML.
  5. Phục vụ bản đồ. Bảng chỉ số theo ô được tiling thành lớp hexbin/heatmap đưa lên dashboard (deck.gl/Superset), theo đúng nguyên tắc ở trực quan hoá.

Kết quả: phân tích không kịp làm nổi trên một Postgres trở thành job đêm vài phút; điểm mấu chốt không phải "mua máy to hơn" mà là đổi mô hình — thôi so hình học, chuyển sang lưới H3 và GROUP BY. Với dữ liệu vận hành nhỏ (ATM, ranh giới tỉnh) NCB vẫn giữ PostGIS; chỉ khối tỉ-dòng mới lên warehouse/Spark.

Ghi nhớ

  • Điểm gãy: khi dữ liệu không gian lên trăm triệu–tỉ dòng (giao dịch/ATM có toạ độ, log GPS, ảnh vệ tinh) và cần phân tích hàng loạt, một PostGIS đơn không đủ — chuyển sang warehouse đám mây hoặc Spark.
  • Warehouse GIS: BigQuery GIS (kiểu GEOGRAPHY, hàm ST_*, ST_DWithin), Snowflake Geospatial, Redshift — phân tích tỉ dòng bằng SQL ngay trong kho, không cần hạ tầng GIS riêng; bộ hàm hẹp hơn PostGIS và dễ đắt nếu quét ẩu.
  • Spark + Apache Sedona (GeoSpark): spatial join phân tán có chỉ mục và xử lý raster trên cụm — hợp ETL không gian nặng; xem Spark.
  • Lưới phân cấp là chìa khoá: Uber H3 (lục giác), Google S2, geohash, quadkey biến toạ độ thành cell_id, giảm spatial join thành GROUP BY / equi-join — nhanh hơn bậc độ lớn, đổi độ chính xác hình học lấy quy mô.
  • Định dạng cloud-native: GeoParquet (cột, phân tán), COG (raster đọc từng phần qua HTTP), zarr — chia nhỏ, đọc chọn lọc từ object storage.
  • Kiến trúc: nguồn → lakehouse (GeoParquet/COG) → gán H3/S2 + phân vùng theo ô → phân tích (GROUP BY cell_id) + tiling phục vụ bản đồ.
  • Đánh đổi: PostGIS (giao dịch, chính xác hình học, quy mô vừa) vs warehouse/Spark (quy mô tỉ dòng, batch). Mẹo: index bằng lưới, phân vùng theo ô, tránh spatial join thô ở quy mô lớn.
  • Trên sandbox chỉ câu GROUP BY c.city trên transactions/accounts/customers chạy thật — analogy thu nhỏ của "gom theo ô H3"; mọi SQL BigQuery/Snowflake/Spark và hàm không gian là minh hoạ.

Bài viết liên quan

Các kỹ thuật phân tích không gian tạo giá trị kinh doanh cho ngân hàng: phân tích mật độ & hotspot, gom cụm ST_ClusterDBSCAN/KMeans, tự tương quan không gian (Moran's I), chọn địa điểm ATM/chi nhánh bằng service area, isochrone và overlay đa lớp. Nối tiếp bài truy vấn không gian, minh hoạ bằng SQL PostGIS và quy trình site selection.

13 thg 7, 2026 4

Biến dữ liệu không gian thành bản đồ để ra quyết định. Bản đồ chuyên đề: choropleth (phải chuẩn hoá), symbol/bubble, heatmap, cluster, flow map — chọn theo dữ liệu. Công cụ: QGIS, Leaflet/Mapbox GL/deck.gl/Kepler.gl, bản đồ trong Power BI & Superset; tile OSM, level of detail. Luồng PostGIS → GeoJSON (ST_AsGeoJSON) → web map, nguyên tắc thiết kế và cạm bẫy. Bối cảnh NCB: dashboard dư nợ/huy động/khách theo tỉnh cho lãnh đạo.

13 thg 7, 2026 3

PostGIS biến PostgreSQL thành cơ sở dữ liệu không gian đầy đủ. Bài này đi từ cài đặt CREATE EXTENSION, kiểu geometry vs geography, SRID/EPSG:4326, cách nhập điểm bằng ST_MakePoint/ST_GeomFromText, các hàm cốt lõi (ST_Distance, ST_DWithin, ST_Contains, ST_Buffer, ST_Transform...), chỉ mục GIST bắt buộc cho hiệu năng, tới bài toán tìm ATM/chi nhánh trong bán kính quanh khách hàng NCB.

13 thg 7, 2026 3

Nhập môn dữ liệu không gian (spatial/geospatial): dữ liệu gắn vị trí trên Trái Đất, các loại hình học điểm/đường/vùng, hệ toạ độ CRS/SRID (WGS84, UTM/VN2000), vector vs raster, quan hệ và phép đo không gian. Đặt nền cho cả series GIS và giá trị của nó với ngân hàng NCB: mạng lưới chi nhánh/ATM, phân tích khách hàng theo địa bàn, rủi ro và gian lận theo vị trí.

13 thg 7, 2026 3