**ジオジョインをH3インデックスで400 倍高速化した手法**

- **問題点:** 大規模な空間データセットに対する従来のジオジョインクエリは、ポイント‐イン‐ポリゴン判定やテーブル全体のスキャンが必要だったため遅延が大きかった。
- **解決策:** Uber の H3 ヘキサゴナル階層インデックスシステムを利用し、空間情報を固定サイズセルへ事前集約した。
- **実装手順:**
  1. すべてのジオメトリ(点・線・多角形)を適切な解像度で対応する H3 インデックスに変換する。  
  2. 生成されたインデックスを別テーブルに格納し、H3 キーで索引付けする。  
  3. ジョイン時には、重複した H3 インデックスをキーとしてマッチさせ、膨大な空間判定処理を回避する。  
- **結果:** クエリ遅延が数時間から数分へと短縮され、約 400 倍の高速化を実現。また、選択した解像度内であれば空間的正確性は維持された。

ジオメトリ比較を単純な整数キー検索に置き換えることで、データの忠実度を損なうことなく大幅なパフォーマンス向上を達成しました。

2026/02/05 20:19

**ジオジョインをH3インデックスで400 倍高速化した手法** - **問題点:** 大規模な空間データセットに対する従来のジオジョインクエリは、ポイント‐イン‐ポリゴン判定やテーブル全体のスキャンが必要だったため遅延が大きかった。 - **解決策:** Uber の H3 ヘキサゴナル階層インデックスシステムを利用し、空間情報を固定サイズセルへ事前集約した。 - **実装手順:** 1. すべてのジオメトリ(点・線・多角形)を適切な解像度で対応する H3 インデックスに変換する。 2. 生成されたインデックスを別テーブルに格納し、H3 キーで索引付けする。 3. ジョイン時には、重複した H3 インデックスをキーとしてマッチさせ、膨大な空間判定処理を回避する。 - **結果:** クエリ遅延が数時間から数分へと短縮され、約 400 倍の高速化を実現。また、選択した解像度内であれば空間的正確性は維持された。 ジオメトリ比較を単純な整数キー検索に置き換えることで、データの忠実度を損なうことなく大幅なパフォーマンス向上を達成しました。

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

Summary

この記事は、コストの高い空間述語をH3ベースの集合演算に置き換えることで、遅い二次元空間結合をコンパクトなキーで高速ハッシュ結合へと変換する方法を示しています。各ジオメトリを解像度 3 の少数の H3 セルで覆うことにより、結合は最初にセルを共有する候補ペアをフィルタリングし、その後で正確な

ST_Intersects
をその候補のみに適用します。これにより、潜在的に何百万もの交差チェックが、フィルタ済みセットだけに減少し、テストで 400 倍の速度向上を実現しています。この手法は CTE、ビュー、およびサブクエリとシームレスに機能し、追加のマテリアライズドテーブルやスキーマ変更は不要です。したがって、精度を下げるなどの実験も容易になります。高い H3 解像度では偽陽性が減少しますが、形状ごとのセル数が増加し、低解像度ではインデックス作成が簡単ですが、解像度 4 を超えるとセル数の増加により急激に大きくなります。実際には、この書き換えにより 15 ワーカーの Xeon クラスターで結合時間を約 459 秒から約 1.2 秒へ短縮し、正確な一致精度(最終的な
ST_Intersects
によって偽陽性が除去される)を維持したまま高速な空間分析を可能にしています。

本文

Geo ジョインは無害に見える

SELECT *
FROM A
JOIN B
  ON ST_Intersects(A.geo, B.geo);

しかしスケールが大きくなると、日常を台無しにするクエリになることがあります。
ジオスペーシャル関数はコストが高く、テーブルが増えるにつれて二次的なループジョインを強制されるため、計算量が指数的に膨れ上がります。

この記事の核心はシンプルです:Floe がこのようなクエリを自動で書き換え、H3 インデックスを活用して劇的に高速化する仕組みを見ていきます。


ジオジョインとは?

ジオジョイン とは

ON
節が空間述語(spatial predicate)になっている任意の結合です。

  • ST_Intersects
  • ST_Covers
  • ST_DWithin

代表例:

SELECT *
FROM A
JOIN B
  ON ST_Intersects(A.geo, B.geo);

なぜスケールで苦しいのか

現代のデータベースは結合をハッシュジョインに変換して高速化します。
結合キーで両入力をハッシュパーティションすると、各ワーカーは自分の部分だけを比較すればよくなり、計算量が二次から一次へと減ります。

空間述語は明確な結合キーを与えないため、以下のような悪い状況に陥ります:

  • すべての値同士を比較しなければならず(二次計算)
  • 各候補ペアに対して高価な述語がかかる

この「逃げたい」状態です。


H3 に出会う

H3(元は Uber が開発)は地球をほぼ六角形セルの階層構造で分割します。

重要な2点:

  1. 階層的解像度 – 粗から細へとレベルを選べる
  2. コンパクトキー – 各セルは
    BIGINT
    で、ハッシュ可能・ソート可能・分散可能

最も重要なのは、ジオメトリをそのカバーするセル ID の集合として表せる点です。
二つの形状が交差すれば、その H3 カバーセットは少なくとも一つ以上のセルを共有します。

これにより「この二つの図形は交差するか?」という問いを「この二つの集合は重なっているか?」へ書き換え、データベースが単純な等値結合として実行できます。


収束的近似(偽陽性のみ)

  • セルカバレッジは正確なジオメトリの近似です。
  • 余分な候補を残しておく(偽陽性)は OK:後で正確述語で除去されます。
  • 真のマッチを逃す(偽陰性)は NG:事前フィルタで落としてしまえば、後段で回復できません。

したがってカバレッジは形状を過剰に近似します(カバー内に形状が含まれる)。


ジオメトリ述語から集合演算へ

書き換え:正確な結合 → 速いフィルタ + 正確再検査

ベースライン

SELECT *
FROM A
JOIN B
  ON ST_Intersects(A.geo, B.geo);

H3 を使う(プランナーがフィルタフェーズを挿入)

  1. A
    の H3 カバレッジを生成
  2. B
    の H3 カバレッジを生成
  3. セルで等値結合(高速整数ジョイン)
  4. 重複候補の除外(同じペアが複数セルにマッチする場合)
  5. 正確述語を候補だけに適用

実際のテンプレート

WITH
  a_cells AS (
    SELECT
      a.id,
      a.geo,
      c.cell
    FROM A a
    JOIN h3_coverage(a.geo, /* resolution */ 3, /* full cover */ true) c
      ON TRUE
  ),
  b_cells AS (
    SELECT
      b.id,
      b.geo,
      c.cell
    FROM B b
    JOIN h3_coverage(b.geo, 3, true) c
      ON TRUE
  ),
  candidates AS (
    SELECT DISTINCT
      a_cells.id   AS a_id,
      a_cells.geo  AS a_geo,
      b_cells.id   AS b_id,
      b_cells.geo  AS b_geo
    FROM a_cells
    JOIN b_cells USING (cell)
  )
SELECT *
FROM candidates
WHERE ST_Intersects(a_geo, b_geo);

データベースが「無料」で得られるもの

この書き換えにより、重い作業は

(cell)
上の等値結合になります:

  • 整数ジョイン → ハッシュコストが低い
  • 自然に分散可能 →
    cell
    でハッシュパーティションできる
  • 高価な述語は後処理になるだけ

読者がよく問う三つの質問

質問回答
近似ってどうなの?はい、H3 ステップは近似で事前フィルタです。正確性は最終的な再チェックで保証されます。
偽陽性が増えるのでは?そうです。期待通りに動きます。目的は候補セットを十分減らし、正確チェックを安価にすることです。
解像度はどう選ぶの?解像度はトレードオフノブです。高いほど偽陽性が減りますが、形状ごとのセル数が増えます。(後述の Numbers で測定方法を紹介)

効果を見る

ユーザーが「国とその中にある都市」を結合する簡単なクエリを入力すると、プランナーは自動的に書き換えを適用します:

EXPLAIN ANALYZE
SELECT *
FROM world_cities
JOIN countries
  ON ST_Intersects(world_cities.geo, countries.geo);

出力

Planning time: 2.291 ms

rows_actual    node
     142141    SELECT
     142141    FILTER WHERE ST_INTERSECTS(MAX(MAX(world_cities.geo)), MAX(MAX(countries.geo)))
                 geojoin filtered rows ratio: 99.62%
     199848    GROUP BY (countries.rowunique, world_cities.rowunique)
     199848    DISTRIBUTE ON HASH(world_cities.rowunique),HASH(countries.rowunique))
     199848    GROUP BY PARTIAL (countries.rowunique, world_cities.rowunique)
     224075    INNER HASH JOIN ON (COALESCE(h3_coverage_geodesic.h3_coverage_geodesic , $1 , const )  = COALESCE(h3_coverage_geodesic.h3_coverage_geodesic , $0 , const ) )
     147043    |-DISTRIBUTE ON HASH(COALESCE(h3_coverage_geodesic.h3_coverage_geodesic , $0 , const ) )
     147043    | LEFT OUTER FUNCTION JOIN H3_COVERAGE_GEODESIC(world_cities.geo, 3, t, t) ON true
     147043    | SCAN world_cities
      17223    |-BUILD HASH
      17223      DISTRIBUTE ON HASH(COALESCE(h3_coverage_geodesic.h3_coverage_geodesic , $1 , const ) )
      17223      LEFT OUTER FUNCTION JOIN H3_COVERAGE_GEODESIC(countries.geo, 3, t, t) ON true
        256      SCAN countries

142141 rows returned
Read: 16.92MiB, Distributed: 5.85GiB, Network: 8.00GiB
Execution time: 1220.118 ms

書き換えが無ければ、国×都市のペアは 256 × 147043 = 37.6 million 通りに膨れ上がります。
対照的に、今回の実装では

ST_Intersects
199 848 回 呼び出し、そのうち 142 141 ペア を残すことで 99.6 % の削減 を達成しています。


オンザフライインデックス

一つの方法は、行 ID → H3 セルリストというインデックスタブルを作り、維持することです。
これにより、H3 インデックス計算のやや高価なステップを省けます。

しかし我々は別の道を選びました:クエリ時にカバレッジを生成し、書き換えに組み込みます。

実用性が高い理由

  • ビュー・CTE・サブクエリにも適用できる
  • 追加ストレージやインデックスメンテナンス不要
  • 解像度・カバレッジモード・述語タイプを試しやすい

これにより、クエリ内で直接データクリーニングを行うことが簡単になります:

WITH cleaned_cities AS (
  SELECT DISTINCT st_reduceprecision(geo, 100) AS geo
  FROM world_cities      -- 100 m 未満の距離にある都市を重複除去
)
SELECT COUNT(*)
FROM countries
JOIN cleaned_cities
  ON ST_Intersects(countries.geo, cleaned_cities.geo);

数値実験

対象データ:国を表す 256 個のポリゴン と、世界都市を表す ポイント の結合。

SELECT *
FROM world_cities
JOIN countries
  ON ST_Intersects(world_cities.geo, countries.geo);

このセットでは

countries.geo
は平均約 418 頂点の多角形(またはマルチポリゴン)です。
15 台のワーカー(Xeon E5‑2695、16 コア @ 2.10 GHz、1 TB メモリ)で実験しました。

まず H3 解像度を変えたときの効果を見てみましょう。
解像度を 1 増やすごとにセルの平均サイズは約 6 倍 減ります。

Resolutionベースラインクエリ時間 (s)GeoJoin 時間 (s)Speedup国インデックス時間 (s)都市インデックス時間 (s)合計インデックスタイム (s)GeoJoin‑Index 時間 (s)インデックス時間 / GeoJoin 時間平均六角形面積 (km²)
0459.716.228.30.20.030.216.00.04 357 449
1459.73.0152.70.10.00.12.90.0609 788
2459.71.4338.80.10.00.11.20.186 801
3459.71.1392.50.30.00.30.90.312 393
4459.72.2205.01.40.01.40.90.61 770
5459.713.234.88.20.08.34.90.6252

**最高解像度(3)では GeoJoin が 1.17 秒、つまり 400 倍 の高速化を実現しています。

さらに時間の内訳を見ると:

観察
低解像度ではインデックス作成が非常に速い(解像度2で全体時間の10%未満)。
解像度4以降、インデックスタイムは急増。
高解像度でも行数が多くなると GeoJoin 時間が再び増加する。

結論

空間述語を H3 セル上の集合演算に書き換えることで、データベースが得意とする 並列ハッシュジョイン を活用できます。
これにより地理情報操作の速度は劇的に向上します。

さらに改善できる点として、例えば「大きなポリゴン内に十分に深く入っているポイント」では空間述語を呼び出さないようにするなどがあります(次回 Numbers で実装例を紹介予定)。

同じ日のほかのニュース

一覧に戻る →

2026/02/07 6:51

**OpenCiv3:サイクリズム・III のオープンソースでクロスプラットフォーム化した再構築**

## Japanese Translation: OpenCiv3は、Civilization IIIのオープンソースでクロスプラットフォームなリメイクであり、レガシー制限を取り除き、モッドサポートを拡張しつつもコアゲームプレイを保持します。Godot EngineとC#で構築されており、Windows、Linux、macOS上でネイティブに動作し、専用のCivilization IIIファイルは不要です(ただしローカルコピーがあると互換性が向上します)。 現在のプレアルファ版(v0.3「Dutch」、2025年12月)は、OS固有のzipまたはtgz(「スタンドアロンモード」でプレースホルダーグラフィック付き)として配布されます。インストール手順は以下の通りです。 - **Windows** – zipを解凍し、`OpenCiv3.exe` をダブルクリックします。ブロックされている場合は解除し、自動検出できない場合は環境変数 `CIV3_HOME` にCivilization IIIフォルダーのパスを設定してください。 - **Linux** – `.tgz` を解凍し、`export CIV3_HOME="/path/to/civ3"` としてから `OpenCiv3.x86_64` を実行します。 - **macOS** – zipを解凍し、`xattr -cr /path/to/OpenCiv3.app` でクォータリゼーションを解除し、同様に `CIV3_HOME` を設定してターミナルから起動します。 既知の問題としてはプレースホルダー資産、不完全なBIQ/SAVファイルサポート(クラッシュを引き起こす可能性があります)、および新規ゲーム開始時にマップ生成用保存ファイルが欠如しているためmacOSでクラッシュするケースがあります。最低ハードウェア要件はまだ公開されていません。プロジェクトはMITライセンスの下でリリースされ、Firaxis、CivFanatics.com、その他の団体とは独立しています。 開発者はBIQ/SAVサポートの完全復元、プラットフォーム別クラッシュ(特にmacOS)の修正、後半ゲームコンテンツの追加、およびグラフィックと安定性の向上に積極的に取り組んでいます。バグや機能要望はGitHubで追跡されており、コミュニティからの貢献が奨励されています。 モッドフレンドリーでクロスプラットフォームな基盤を提供することで、OpenCiv3はプレイヤーと開発者にオリジナルIPを侵害せずにクラシックなCivilization体験を拡張する機会を提供します。

2026/02/07 1:20

Waymoワールドモデル

## Japanese Translation: > **Waymoは、Waymo World Modelという生成シミュレーションエンジンを公開しました。このエンジンは、極端な天候・自然災害・象やロングホーンのような珍しいオブジェクト、逆走トラックなど安全に関わるインシデントを含むハイパーリアリスティックな自律運転シナリオを生成します。** > Google DeepMind の Genie 3 をベースにしたこのモデルは、カメラと LiDAR データを融合し、ドライビングアクション制御・シーンレイアウト制御・時間帯、天候、カスタムシナリオを調整する言語プロンプトという3つの制御機構を提供します。録画済みまたは新規生成されたルートに対して代替ドライビング決定を評価する「what‑if」反実仮想シミュレーションもサポートしています。 > Waymo Driver は米国都市で約 2 億マイルの完全自律走行距離を記録し、数十億マイルに相当するバーチャル走行をシミュレートしてきました。World Model はリアルなダッシュカムやモバイルカメラ映像を多模態シミュレーションへ変換し、正確な視覚シーンと一致させることでこの機能を拡張します。効率的なバリアントは実時間の最大4倍速で動作し、計算資源を削減しつつ長時間テストが可能です。 > このシステムは、安全性が証明された自律運転を実現するために Waymo の AI エコシステムの重要柱となっており、Waymo と Google DeepMind からなる大規模チームによって開発されています。

2026/02/07 6:33

**Show HN:** 「見てください、Linux なしで実現!ESP32‑S3/BreezyBox 上のシェル・アプリインストーラ・Vi・Cc」

## 日本語訳: BreezyBox – ESP32‑S3を小型の即時起動PCに変える BreezyBox は ESP‑IDF 用のミニシェルコンポーネントで、ESP32‑S3 ボードを小さな即時起動 PC に変えることができます。FreeRTOS(完全な OS ではない)上で実行され、自身のシェル、コードエディタ、コンパイラ、およびオンラインアプリインストーラを統合しています。このコンポーネントは stdio サポート付きの任意の ESP‑IDF プロジェクトにインポートできます。 ### コア機能 - **仮想端末と UNIX ライクなコマンド**(現在作業中のディレクトリを追跡) - **アプリインストーラ**:個人リポジトリから ELF バイナリをダウンロードし、既存の `elf_loader` ダイナミックリンカで実行 - **表示処理はユーザーフームウェアに任せる**:デモでは stdout を LVGL テキストラベルコントロールで表示(ほとんどの LCD で動作)。好きなグラフィックススタックに置き換え可能 - **オプションの高フレームレートフォントレンダラー**(やや大きいディスプレイでは約30FPS)を作者が実装済みだが必須ではない ### デモと柔軟性 サンプルデモは Waveshare ESP32‑S3‑Touch‑LCD‑7B ボードで動作しますが、コードは他のディスプレイやヘッドレスボードに適応できます。$10 程度の 2 インチ LCD S3 開発ボードまたは USB コンソール付きヘッドレスボードを開始点として推奨しています。 ### メモリと制約 ESP32‑S3 のメモリが限られているため、ユーザーは PSRAM アラインメントやその他の quirks を確認しながら大きなアプリケーションを実行する必要があります。BreezyBox はオーバーヘッドを最小化しつつ ELF 実行を可能にするよう設計されています。 ### コミュニティと拡張性 - MIT ライセンス;貢献は歓迎(特にテスト、共有例、異なるボードや言語用の新しいファームウェアリポジトリ) - プロジェクトは他 CPU への移植(例:RISC‑V P4/P6)や様々な GUI スタイルを備えた完全なファームウェアリポジトリ作成を推奨 ### インパクト ESP32‑S3 上で低オーバーヘッドの ELF 実行を可能にすることで、BreezyBox はメイカー、教育者、プロトタイプ開発者の可能性を拡大し、小型組み込みデバイスに PC ライクな機能を採用するホビイストコミュニティを刺激します。

**ジオジョインをH3インデックスで400 倍高速化した手法** - **問題点:** 大規模な空間データセットに対する従来のジオジョインクエリは、ポイント‐イン‐ポリゴン判定やテーブル全体のスキャンが必要だったため遅延が大きかった。 - **解決策:** Uber の H3 ヘキサゴナル階層インデックスシステムを利用し、空間情報を固定サイズセルへ事前集約した。 - **実装手順:** 1. すべてのジオメトリ(点・線・多角形)を適切な解像度で対応する H3 インデックスに変換する。 2. 生成されたインデックスを別テーブルに格納し、H3 キーで索引付けする。 3. ジョイン時には、重複した H3 インデックスをキーとしてマッチさせ、膨大な空間判定処理を回避する。 - **結果:** クエリ遅延が数時間から数分へと短縮され、約 400 倍の高速化を実現。また、選択した解像度内であれば空間的正確性は維持された。 ジオメトリ比較を単純な整数キー検索に置き換えることで、データの忠実度を損なうことなく大幅なパフォーマンス向上を達成しました。 | そっか~ニュース