Web開発
ブラウザで1GBのGMLファイルを読み込もうとしたユーザーから学んだこと
What we learned when a user tried to load a 1 GB GML file in a browser (geodataviewer.com)
要約
1GBもの巨大なGMLファイルがブラウザで読み込めない問題は、メモリ飽和、解析の遅延、レンダリングの限界に起因します。この問題を解決するため、ベクトルタイルは現在の表示範囲とズームレベルに必要なデータのみを読み込むことで、メモリ使用量とパフォーマンスを劇的に改善します。これは、Web上の地理空間データを扱う上で、フラットファイルからタイル化されたアーキテクチャへの移行が不可欠であることを示しています。
全文翻訳
ブラウザで巨大なGMLファイルを読み込もうとした際に学んだこと。
従来のGISフォーマットがスケールで破綻する理由、ベクトルタイルがメモリとレンダリングのボトルネックをどのように解決するか、そしてフラットファイルからタイル化されたアーキテクチャへの移行がWebベースの地理空間データに何を意味するかを学びましょう。
この問題の始まり
数週間前、GeoDataViewerのユーザーから、巨大なGMLファイルがブラウザに読み込めない理由について問い合わせがありました。そのファイルは、国の地質図であり、サイズは約1GBで、何十万もの地物を含んでいました。ユーザーはオープンデータをダウンロードし、解凍し、Webマップにドラッグしましたが、何も起こりませんでした。
これはバグレポートではありません。これはフォーマットの問題です。そして、これは一人のユーザーよりもはるかに大きな問題です。
毎日、GISの専門家、地質調査員、都市計画家、ホビイストが同じ壁にぶつかっています。彼らは完璧なオープンデータを取得し、モダンなWebブラウザで表示しようとしますが、ブラウザはただ…諦めてしまいます。
解決策は存在します。10年以上前から存在しています。しかし、ほとんどのエンドユーザーはそれを知りません。この記事では、なぜベクトルタイルが答えなのか、なぜ部分的な解決策が不十分なのか、そして「自分のデスクトップGISでは動作する」と「ブラウザで動作する」の間のギャップが、この業界で最も過小評価されているUXの問題であり続ける理由について説明します。
パートI:なぜブラウザは巨大なベクトルデータセットを扱えないのか
ブラウザはQGISではありません。ArcGIS Proでもありません。それは、厳格なメモリ予算、単一スレッド(に近い)DOM、ディスクへのアクセス権を持たないサンドボックス化された実行環境です。
約1GBのGMLファイルをWebマップにドラッグすると、何が起こるかを見てみましょう。
ステップ1:メモリ飽和
ブラウザはファイル全体をメモリに読み込む必要があります。GMLは、すべてのXML派生フォーマットと同様に、悪名高いほど冗長です。約1GBのGMLファイルは、約1GBのXMLテキストに展開されます。これをDOMツリーに解析すると、単純なパーサーではピークメモリが3〜5GBになります。GeoJSONを出力するストリーミングパーサーでさえ、そのデータをメモリ内のデータ構造に具体化する必要があります。結果として得られるGeoJSONは、レンダリングが開始される前にブラウザがデータセット全体をメモリに保持することを必要とします。8GBのRAMを搭載した典型的なラップトップ上のChromeはクラッシュするか、スワップで死ぬか、メモリ不足のエラーを発生させます。
ステップ2:解析のボトルネック
JavaScriptでのXML解析は遅いです。DOMParserは、数百メガバイトのドキュメント用に最適化されていません。ブラウザのメインスレッドは、ドキュメントツリーを構築しようとしている間、数十秒から数分間ブロックされます。イールドも、プログレスバーもなく、フリーズしたタブと回転するカーソルだけです。
ステップ3:レンダリングの崩壊
データがGeoJSONとしてメモリに格納されたとしても、何十万もの地物をレンダリングすることはそれ自体が課題です。各地物は、キャンバスレンダリングパイプラインのDOM要素になります。パンやズームごとに、可視性が再評価され、座標が再投影され(事前に再投影するのを忘れた場合 - 2番目のブロッキング操作)、再描画されます。タイル化されていない場合、レンダラーは各フレームですべての地物を考慮する必要があります。フレームレートは1 FPSを下回ります。ユーザーは諦めます。
なぜこれがすべてのフラットフォーマットに影響するのか
これはGMLの問題ではありません。これは、タイル化されていないすべてのベクトルフォーマットの問題です。
フォーマット ブラウザの問題 巨大データセットのメモリ
GML XML解析が遅くメモリを大量に消費; ネイティブブラウザサポートなし ~3–5 GB (DOM)
Shapefile (.shp) バイナリパーサーが必要; レンダリング前に完全にロードする必要がある ~600 MB–1 GB (非圧縮)
GeoJSON 事実上の標準だが、ストリーミングなし; 最初の描画前にファイル全体を解析する必要がある ~700 MB+
GeoJSON Lines (.geojsonl) 行ごとにストリーミング可能だが、単一レイヤーとしてメモリに保持する必要がある ~700 MB (ロード中のピークは減少)
GeoParquet 列指向で分析に効率的; ブラウザでWASMまたはDuckDBが必要; ネイティブレンダリングサポートなし クエリによる - より良いが、複雑なツールが必要
これらのフォーマットはすべて、同じ根本的な制限を共有しています。クライアントは、レンダリングを開始する前にデータセット全体をロードする必要があります。
「しかし、デスクトップGISはそれを扱える」— いいえ、扱えません
この時点でよくある反応は、「ブラウザは弱い。QGISやArcGISを使えばいい。それらはこのために作られている」というものです。
不快な真実:それらも苦労しています。約1GBのGMLファイルをQGISに読み込むには、最新のラップトップで5〜10分かかることがあります。その間、アプリケーションはフリーズしたままです。パンもズームも属性テーブルも、ステータスバーのあいまいな「読み込み中…」以上のプログレスバーもありません。ArcGIS Proは地物数では優れていますが、何十万もの地物と完全なジオメトリに対するメモリフットプリントは1.5〜2.5GBです。これは、属性テーブルを開いたり、シンボロジー分類を適用したり、マップをエクスポートしようとする前のことです。8GBのRAMを搭載したマシンでは、スワップ領域に入ることになります。
これはブラウザ対デスクトップの問題ではありません。これはデータモデルの問題です。フォーマットが、画面へのレンダリングであれ、空間クエリの実行であれ、あらゆる操作の前にすべてのジオメトリをメモリにロードする必要がある場合、ボトルネックは同じです。デスクトップGISはより大きな予算(より多くのRAM、直接ディスクアクセス、ネイティブスレッド)を持っていますが、異なるアーキテクチャを持っているわけではありません。データセット全体がメモリに着地します。違いは程度です。デスクトップアプリケーションはクラッシュする代わりに5分かかるかもしれませんが、ユーザーはまだ待っています。そして、そのデータを同僚とWebで共有する必要がある瞬間、彼らは結局ブラウザの壁にぶつかります。
パートII:ベクトルタイルの解決策
ベクトルタイルは、 deceptively simple な洞察でこのサイクルを破ります。すべてをロードしない。現在のズームレベルで表示されるものだけをロードします。
ベクトルタイルは、事前にタイル化され、事前にクリップされたデータチャンクです。通常、特定のズームレベルで256×256または512×512ピクセルで、コンパクトなバイナリフォーマット(Mapbox Vector Tile / MVT、PBF)でエンコードされています。ブラウザは、ユーザーがパンやズームするにつれてオンデマンドでタイルを要求します。各タイルは通常10〜100KBです。国のデータセットを表示するセッションでは、完全なGeoJSONペイロードの代わりに、数個のタイル(合計数メガバイト)しか取得しない場合があります。
仕組み
生データ(GML、Shapefile、GeoJSON)
│
▼ [ETL / 変換パイプライン]
│
├── WebフレンドリーなCRSに再投影
├── ジオメトリの単純化(Douglas-Peucker、Visvalingam)
├── タイル境界へのクリッピング
├── MVT(Protocol Buffers)としてエンコード
└── タイルピラミッドの書き込み(MBTiles / PMTiles / ディレクトリ)
│
▼ タイルサーバー / ストレージ
│
├── CDNまたはS3上の静的ファイル
├── PMTiles(単一ファイルアーカイブ)
└── タイルサーバー(Tegola、Martin、TileServer GL)
│
▼ クライアント(MapLibre GL / Mapbox GL / Leaflet)
│
├── ビューポート+ズームでタイルを要求
├── MVTをWebGLジオメトリにデコード
├── オンザフライでスタイル設定(ペイント、塗りつぶし、ラベル)
└── 60 FPSでレンダリング
なぜうまくいくのか
クリッピング。各タイルには、その境界ボックスと交差する地物(または地物の断片)のみが含まれます。100kmにまたがる地物は数十個のタイルに分割されますが、ズーム10では、各タイルには単純化された数個のセグメントしか含まれない場合があります。
単純化。低ズームレベルでは、ジオメトリは積極的に単純化されます。半島のとがった海岸線は10頂点の線になります。ピクセルが小さすぎて気づかないため、単純化はユーザーには見えませんが、タイルサイズを桁違いに削減します。
ズームレベル選択。地物はズームレベルでフィルタリングできます。小さな道路はズーム12+でのみ表示されます。市境はズーム8+で表示されます。レンダラーは表示できないデータを受信することはありません。
オンデマンドロード。ブラウザは、現在のビューポートのタイルを正確にロードします。中央ストックホルムを調べているユーザーは、国全体ではなく、その地域のタイルをロードします。
実際の数値
上記のようなデータセット(何十万もの地物、約1GBのGML)の場合:
アプローチ サイズ メモリ ロード時間 パン/ズーム
生のGMLドラッグ&ドロップ ~1 GB 3–5 GB (クラッシュ) 数分 (ブロック) N/A
GeoJSON (事前変換済み) ~750 MB ~750 MB ~10秒 解析 ~5 FPS
GeoJSON + geojson-vt ~750 MB ~750 MB ~10秒 解析 ~30 FPS
ベクトルタイル (MVT) ~50–150 MB 合計 <100 MB (ビューポートのみ) <1秒 初期 60 FPS
ズームレベル0〜14の国の地質図のベクトルタイルピラミッドは、適切な単純化を伴って、約100MBのMVTデータに圧縮されます。そして、ほとんどのセッションでは、そのうち10MB以上をダウンロードすることはありません。