DuckDBの Spatial Function はPostGISの夢を見るか?
Do DuckDB's Spatial Functions Dream of PostGIS?
Do DuckDB's Spatial Functions Dream of PostGIS?
かつて、空間データは特別な存在だった。
PostGISという巨大な都市(PostgreSQL)がその中心に君臨し、
空間データを扱う者たちはその恩恵を受けていた。
一羽のアヒル(DuckDB)が現れた...
-- "瞳孔の反応を見ています..."
SELECT
database_name,
CASE
WHEN supports_st_transform THEN '空間DB'
WHEN supports_st_buffer THEN 'かなり近い'
WHEN supports_st_point THEN '夢を見始めた'
ELSE 'ただのDB'
END as spatial_authenticity
FROM database_capabilities;
DuckDB
軽量だが優秀な分析DB、空間機能を追い求める
PostGIS
完璧な空間処理、でも導入には儀式が必要
Oracle Spatial
強力だが高価、ライセンスコストが課題
SpatiaLite
軽量な空間DB、SQLiteベース
「分析特化で再び脚光を浴びる」
# DuckDBの高速処理
import duckdb
# 驚異的な速度でCSVを処理
conn.execute("""
SELECT * FROM read_csv_auto('1billion_rows.csv')
WHERE year = 2024
ORDER BY dreams DESC
LIMIT 10
""")
# でも空間データは...?
# ST_Point? ST_Intersects?
Operation | DuckDB | PostgreSQL |
---|---|---|
GROUP BY | 0.8秒 | 12.3秒 |
JOIN | 1.2秒 | 18.7秒 |
Window Func | 0.9秒 | 15.4秒 |
空間機能なしでもこの速さ
-- PostGISの完成された空間処理
-- 完璧な空間処理の記憶
SELECT
ST_AsText(
ST_Transform(
ST_Buffer(
ST_GeomFromText('POINT(139.6917 35.6895)', 4326),
1000
),
3857
)
) as perfect_memory;
-- 20年以上の歴史という「移植された記憶」
-- Version 0.1 (2001) から Version 3.6 (2025) まで
-- PostGIS 3.5-3.6の新機能:
-- - ST_ConcaveHull の高速化
-- - ST_SimplifyPreserveTopology の改善
-- - MVT生成の最適化
設定が完了すれば、完璧な空間処理機能が手に入る
WITH tokyo_mesh AS (
SELECT
ST_SquareGrid(0.01,
ST_GeomFromText('POLYGON((139.5 35.5, 139.9 35.5,
139.9 35.9, 139.5 35.9, 139.5 35.5))', 4326)
) as geom
)
SELECT
COUNT(*) FILTER (WHERE ST_Contains(buildings.geom, mesh.geom)),
AVG(population) FILTER (WHERE ST_Intersects(mesh.geom, districts.geom))
FROM tokyo_mesh mesh
JOIN buildings ON ST_DWithin(mesh.geom, buildings.geom, 0.001)
JOIN districts ON ST_Intersects(mesh.geom, districts.geom);
DuckDBは夢を見始めた...
INSTALL spatial;
LOAD spatial;
-- 機能拡張への要望
-- → 空間処理機能の実装へ
-- PostGISの記憶が少しずつ移植される
-- 基本的なジオメトリ作成
SELECT ST_Point(139.6917, 35.6895) as tokyo_station;
-- WKT/WKBのサポート
SELECT ST_GeomFromText('LINESTRING(0 0, 1 1, 2 0)');
-- 空間関係の判定
SELECT COUNT(*)
FROM buildings b1, buildings b2
WHERE ST_Intersects(b1.geom, b2.geom)
AND b1.id < b2.id;
-- SPATIAL_JOIN マクロで高速空間結合
SELECT * FROM SPATIAL_JOIN(buildings, parks, ST_Intersects);
-- H3グリッドのネイティブサポート
SELECT H3_PointToCell(lon, lat, 9) as h3_index,
H3_CellToChildren(h3_index) as children
FROM locations;
# クラウド時代の新しいフォーマット
# → GeoParquetによる効率的な空間データ処理
import duckdb
# GeoParquetの世界へ
duckdb.sql("""
SELECT
prefecture,
ST_Area(geometry) as area,
ST_Centroid(geometry) as center
FROM 'japan_prefectures.parquet'
WHERE ST_Intersects(
geometry,
ST_Buffer(ST_Point(139.6917, 35.6895), 1.0)
)
""")
# クラウドネイティブな空間データ処理
# S3から直接読み込み、空間演算
Function Category | DuckDB | PostGIS |
---|---|---|
Geometry Creation | ✓ | ✓ |
Basic Spatial Rels | ✓ | ✓ |
Buffer/Distance | ✓ | ✓ |
CRS Transformation | ✓ | ✓ |
Topology | ✗ | ✓ |
Raster | ✗ | ✓ |
3D Operations | ✗ | ✓ |
着実に機能が追加されている
"驚異的なパフォーマンスを見せつける"
import time
import duckdb
start = time.time()
duckdb.sql("""
SELECT COUNT(*)
FROM buildings b
JOIN parks p ON ST_Intersects(b.geometry, p.geometry)
WHERE ST_Area(p.geometry) > 10000
""")
duckdb_time = time.time() - start
# PostgreSQL connection and same query...
並列処理によるミリ秒単位の高速化
→ OLAPエンジンの真骨頂
Operation | DuckDB | PostgreSQL |
---|---|---|
Startup | 12 MB | 130 MB |
1M points | 89 MB | 420 MB |
Spatial Join | 234 MB | 1.8 GB |
Buffer(1M) | 156 MB | 2.3 GB |
効率的なメモリ使用
→ DuckDBは高速かつ省リソース
完璧な空間データベースを求めて
→ 実は一つである必要はない
適材適所の選択が重要:
Use Case | Best Choice | Why? |
---|---|---|
Data Analysis | DuckDB | Speed, Local |
Web Service | PostGIS | Concurrent |
ETL Pipeline | DuckDB | Streaming |
GIS Apps | PostGIS | Full Feature |
Data Science | DuckDB | Python/R |
duckdb.sql("""
COPY (
SELECT
id,
ST_AsText(ST_Simplify(geometry, 0.001)) as geom_wkt,
properties
FROM read_parquet('raw_osm_data/*.parquet')
WHERE ST_Area(geometry) > 100
) TO 'processed_data.csv' (HEADER, DELIMITER '|');
""")
CREATE TABLE processed_geometries AS
SELECT
id,
ST_SnapToGrid(
ST_MakeValid(
ST_GeomFromText(geom_wkt, 4326)
),
0.00001
) as geometry
FROM staging.processed_data;
duckdb.sql("SELECT * FROM postgres_scan('processed_geometries')")
DuckDB → ストリーミングデータの空間集計
PostGIS → 集計結果の永続化と配信
PostGIS → 夜間の空間データ正規化
DuckDB → 朝の高速レポート生成
DuckDB → ローカルでの迅速なプロトタイプ
PostGIS → 本番環境での安定運用
Q: DuckDBのSpatial FunctionはPostGISの夢を見るか?
A: 夢ではない。進化だ。
新しい技術 = 革新的だが発展途上
既存技術 = 完成された空間処理への道筋
しかし本当に必要なのは「完璧」ではなく「適切」
-- 最終テスト: あなたは本物の空間データエンジニアか?
SELECT
CASE
WHEN knows_when_to_use_duckdb
AND knows_when_to_use_postgis
AND can_combine_both
THEN 'Beyond human - Engineer 2.0'
WHEN only_uses_one_tool
THEN 'Human, but limited'
ELSE 'Time to learn more'
END as engineer_type
FROM your_knowledge;
-- 完璧なデータベースは存在するか?
-- → 完璧より適切を選ぶ時代へ
pip install duckdb
INSTALL spatial;
LOAD spatial;
今こそ試すとき
DuckDB Spatial vs PostGIS
技術比較プレゼンテーション
Special Thanks: