100行のGanosコードに基づいて、数億のベクトル空間データのオンライン視覚化を実現します

はじめに:この記事では、Ganos時空間エンジンが提供するデータベース高速表示テクノロジーのRDS PGまたはPolarDB(PGバージョンまたはOracleバージョンと互換性があります)の使用方法を紹介し、100行のコードのみを使用してオンライン高速表示を実現します何億もの大規模な幾何学的空間データのスムーズなマップ相互作用。スライスの保存と効率の問題に注意を払う必要はありません。

著者:李賀

 

01はじめに

時空間データベースで数億のベクトル空間データのオンライン視覚化を実行する方法は、業界では常に問題となっています。従来の方法では、データ量が多いため、視覚化するためにキャッシュスライスに基づいてデータベース内のデータを公開する必要があり、操作プロセスに時間がかかり、考慮すべき問題がたくさんあります。

  • ベクターデータを事前にスライスする場合、データをスライスする必要がある期間はどれくらいですか?適切なレベルはいくつですか?タイルを保存するのに十分なハードディスク容量がありますか?
  • リアルタイムタイルを使用する場合、リアルタイムレンダリングタイルの応答時間を保証できますか?
  • ベクタータイルを使用する場合、小規模なタイルはどのくらいの大きさになりますか?送信がボトルネックになりますか?フロントエンドレンダリングはどのくらいのデータをサポートできますか?

データベース内の大規模なオンラインデータをすばやく閲覧したい場合、「ベースマップサービス」に使用される従来のオフラインスライス作成プロセスはほとんど理解できず、時間と労力がかかり、オンラインで処理できません。ブラックテクノロジーが登場します。この記事では、Ganos時空間エンジンが提供するデータベース高速表示テクノロジーのRDS PGまたはPolarDB(PGバージョンまたはOracleバージョンと互換性があります)の使用方法を紹介し、100行のコードのみを使用して何億もの大規模な幾何学的空間データマップの相互作用のオンライン高速表示とスムーズさ。スライスの保存と効率の問題に注意を払う必要はありません。

02技術的特徴の解釈

Ganosのオンラインクイックディスプレイ処理の中核は、データベースを視覚化に関連付け、新しい視覚化インデックス技術であるスパースベクトルピラミッド(SVP)インデックスを提供することです。SVPには、高速で経済的な2つの重要な機能があります

その中で、クアイはクアイの2つの段階を指します。

  • ピラミッドの作成は高速です。Ganosは空間インデックスを使用してデータを空間で分割し、密度に基づいてスパースベクトルピラミッドインデックスを確立します。これにより、従来のグラフカットプロセスと比較してデータ計算量が90%削減されます。同時に、ピラミッドの作成は完全並列処理モードを採用しており、1億のプロットデータを生成しても、ピラミッドの生成には約10分しかかかりません。
  • 高速データ表示:Ganosは、視覚的な可視性除去アルゴリズムを採用して、Zオーダーの順序に従って表示効果に影響を与えない大量のデータを除外し、リアルタイム表示の効率を高速化します。Ganosは、PNG形式のラスタータイルとMVT形式のベクタータイルの直接出力をサポートしており、1億の土地のようなパターンデータのリアルタイムレンダリングと表示の応答時間は2番目のレベルに達します。

州にも2つの側面があります。

  • ディスクスペースの節約:1億のプロットデータから生成されたピラミッドインデックスは、元のテーブルの5%の余分なスペースしか占有しません。
  • 開発時間を節約:単純なSQLステートメントのみを使用して、ステートメントパラメーターを調整することで表示効果を柔軟に制御できます。

03使用手順

Ganosのクイックディスプレイエンジンは非常に使いやすく、SQL関数は高度にカプセル化されています。クイックディスプレイエンジンを初めて使用する前に、対応する拡張モジュールを明示的に作成する必要があることに注意してください。実行されるステートメントは次のとおりです。

CREATE EXTENSION ganos_geometry_pyramid CASCADE;

上記のステートメントを実行すると、ポップアップエンジンのコンピューティングコンポーネントが読み込まれます。

3.1スパースベクトルピラミッドを構築する

大きなベクトルテーブルを作成してデータをインポートしたとすると、Ganosst_buildpyramidメソッドを使用してベクトルピラミッドを作成できます。

メソッドのプロトタイプは次のとおりです。パラメータの詳細については、公式ドキュメントを参照してください

boolean ST_BuildPyramid(cstring table、cstring geom、cstring fid、cstring config)

注:*読むには左右にスワイプしてください

その中で

  • table:ベクターデータが配置されているテーブルの名前。
  • geom:ベクトル場名。
  • fid:ベクトル特徴レコードの一意の識別子。Int4/ Int8タイプをサポートします。
  • config:json形式の構成パラメーター文字列。
    • この例では、ベクトルピラミッドの名前と使用する論理タイルサイズを指定します(このタイルサイズは実際のタイルではなく、空間の論理的な分割を表すだけです)。

実際の呼び出しは次のとおりです。

ST_BuildPyramid( 'points'、 'geom'、 'gid'、 '{"name": "points_geom"、 "tileSize":512}')

注:*読むには左右にスワイプしてください

pointsテーブルのgeomフィールド用のベクトルピラミッドを作成しました。ピラミッドの名前はpoints_geomとして指定され、ピラミッドの論理タイルサイズは512に設定されています。

3.2グリッドタイルを取得します

グリッドタイルは画像形式のタイルであり、マップタイルの最も広く使用されている形式です。Ganos' ST_AsPngの方法は、動的にオンデマンドでデータベース側のラスタタイルにベクトルデータをレンダリングする機能を提供します。この関数は、最も基本的なラスターシンボル化機能を提供し、データ管理システムなどの複雑なシンボル化を必要としない軽量シーンを対象としています。

メソッドのプロトタイプは次のとおりです。パラメータの詳細については、公式ドキュメントを参照してください

バイトST_AsPng(cstring名、cstringタイル、cstringスタイル)

その中で

  • name:ピラミッドテーブルの名前。
  • tile:タイルインデックスの行番号と列番号(Z_X_Yの形式)。
  • style:レンダリングスタイル。次のパラメータを使用して、レンダリング効果を調整できます。
    • point_size:ポイントサイズ(ピクセル単位)。
    • line_width:線幅。線要素と領域要素の外側の境界に影響します(ピクセル単位)。
    • line_color:ラインレンダリングカラー。ライン要素とエリア要素の外側の境界線に影響します。最初の6桁は16進数の色で、最後の2桁は16進数の透明度です。
    • fill_color:塗りつぶしの色。サーフェス要素で機能します。
    • 背景:背景色。通常、に設定されますFFFFFF00。つまり、純粋で透明です。

実際の呼び出しは次のとおりです。

ST_AsPng( 'points_geom'、 '1_2_1'、 '{"point_size":5、 "line_width":2、 "line_color": "#003399FF"、 "fill_color": "#6699CCCC"、 "background": "#FFFFFF00" } ')

注:*読むには左右にスワイプしてください

ベクトルピラミッドからインデックスの行番号と列番号がx = 2、y = 1、z = 1のベクトルタイルを取得し、構成したスタイルに従ってベクトルタイルをラスタータイルとしてレンダリングし、画像をPNG形式で返します。 。

3.3ベクタータイルを取得する

ベクタータイルは、フロントエンドでスタイルを柔軟に構成できる新しいマップタイルテクノロジーです。WebGLレンダリングを使用すると、効果がより美しくなり、Mapboxなどのマップフレームワークでこの形式を簡単にサポートできます。GanosST_Tileメソッドを使用すると、ベクターピラミッドのデータをベクタータイルの形式で提供できます。

メソッドのプロトタイプは次のとおりです。パラメータの詳細については、公式ドキュメントを参照してください

bytea ST_Tile(cstring name、cstring key);

その中で

  • name:ピラミッドの名前。この例では、テーブルname_vectorフィールド名です。
  • キー:タイルインデックスの行番号と列番号(Z_X_Yの形式)。

標準のTMSの行と列の番号、および呼び出すピラミッドテーブルの名前を指定するだけで済みます。

実際の呼び出しは次のとおりです。

ST_Tile( 'points_geom'、 '1_2_1');

ベクトルピラミッドからインデックスの行と列の番号がx = 2、y = 1、z = 1のベクタータイルを取得し、返されるデータは標準のMVT形式です。

04実例

4.1テストデータ

テスト例として、2セットのベクトルデータを用意します。

建物のテーブルは、合計1億2500万個のデータを含む表面データであり、グリッドタイルを使用したオンライン視覚化効果を示しています。

gid | geom | 
--- | ---------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- --------- | 
  1 | MULTIPOLYGON(((-88.066953 34.916114 0、-88.066704 34.916114 0、-88.066704 34.91602 0、-88.066953 34.91602 0、-88.066953 34.916114 0)))                 
  2 | MULTIPOLYGON(((-87.924658 34.994797 0、-87.924791 34.99476 0、-87.924817 34.994824 0、-87.924685 34.994861 0、-87.924658 34.994797 0)))                

注:*読むには左右にスワイプしてください

ポイントテーブルは、合計107,000個のデータを含むポイントデータであり、ベクタータイルを使用したオンライン視覚化効果を示しています。

 

id | geom | 
-| ------------------------------ | 
 1 |ポイント(113.5350205 22.1851929)| 
 2 |ポイント(113.5334245 22.1829781)|

 

4.2フルスタックアーキテクチャ

データベースクイックディスプレイのフルスタックアーキテクチャには、データベースサーバー、Pythonサーバー、ユーザー側の3つの部分があります。フルスタックアーキテクチャを次の図に示します。

 

1.png

 

4.3サーバーコード

 

コードを簡素化し、論理的な記述に重点を置くために、バックエンド言語としてPython(Python 3.6以降と互換性があります)を選択し、WebフレームワークはPythonベースのFlaskpip install flaskインストール)フレームワークを使用し、データベース接続フレームワークを使用しますPython用のPsycopg2を使用pip install psycopg2ます(インストールに使用)。

最も基本的な機能を実装したことは特筆に値します。Webサービス自体のパフォーマンスがボトルネックになった場合、さまざまなプラットフォームやフレームワークに応じて最適化して、応答パフォーマンスを向上させることができます。

最初にバックエンドにベクトルピラミッドを確立し、次にそれぞれ2つのインターフェイスを実装しました。ベクトルタイルインターフェイスはポイントテーブルのデータを使用しラスタータイルインターフェイスは建物テーブルのデータを使用して、フロントエンドのスタイルを定義します。直接転送します。説明の便宜上、バックエンドコードは、ベクトルラスターの2つのインターフェイスを同時に提供し、実際の使用で必要に応じて選択できます。

 

#-*-コーディング:utf-8-*- 
#@ File:Vector.py 

import json 
from psycopg2 import pool 
from threading import Semaphore 
fromフラスコimport Flask、jsonify、Response、send_from_directory 
import binascii 

#接続パラメーター
CONNECTION = "dbname = postgres user = postgres password = postgres host = YOUR_HOST port = 5432 " 

class ReallyThreadedConnectionPool(pool.ThreadedConnectionPool):
    " ""
    マルチスレッド接続プールの場合、マップタイルクラスの高同時実行シナリオの応答を改善します。
    "" " 
    def __init __(self、 minconn、maxconn、* args、** kwargs):
        self._semaphore = Semaphore(maxconn)
        super().__ init __(minconn、maxconn、* args、** kwargs)

    def getconn(self、* args、** kwargs):
        self._semaphore.acquire()
        return super()。getconn(* args、** kwargs)

    def putconn(self、* args、** kwargs):
        super()。putconn(* args、** kwargs)
        self._semaphore .release()

クラスVectorViewer:
    def __init __(self、connect、table_name、column_name、fid):
        self.table_name = table_name 
        self.column_name = column_name 
        #创建一
        未接self.connect = ReallyThreadedConnectionPool(5、10、connect)
        #約定金字塔表名
        self.pyramid_table = f "{self.table_name} _ {self.column_name}" 
        self.fid = fid 
        self.tileSize = 512 
        #self._build_pyramid()

    def _build_pyramid(self):
        "" "创建金字塔" "" 
        config = { 
            "name":self.pyramid_table、
            "tileSize":self.tileSize 
        } 
        sql = f "select st_BuildPyramid( '{self.table_name}'、 '{ self.column_name} '、' {self.fid} '、' {json.dumps(config)} ') " 
        self.poll_query(sql)
        
    def poll_query(self、query:str):
        pg_connection = self.connect.getconn( )
        pg_cursor = pg_connection.cursor()
        pg_cursor.execute(query)
        record = pg_cursor.fetchone()
        pg_connection.commit()
        pg_cursor.close()
        self.connect。
        レコードがNoneでない場合のputconn(pg_connection) 
            return record [0] 

class PngViewer(VectorViewer):
    def get_png(self、x、y、z):
        #デフォルトのパラメーター
        config = { 
            "point_size":5、
            "line_width":2、
            "line_color": "#003399FF"、
            "fill_color": "#6699CCCC"、
            "background": "#FFFFFF00" 
        } 
        #psycpg2を使用する場合、バイナリデータを16進文字列として返す方が効率的です
        sql = f "select encode(st_aspng( '{self.pyramid_table } '、' {z} _ {x} _ {y} '、' {json.dumps(config)} ')、' hex ') " 
        result = self。poll_query(sql) 
        #16進文字列の形式で返される場合にのみ、変換して戻す必要があります
        result = binascii.a2b_hex(result)
        return result

class MvtViewer(VectorViewer):
    def get_mvt(self、x、y、z):
        #psycpg2を使用する場合、バイナリデータを16進文字列として返す方が効率的です
        sql = f "select encode(st_tile( '{self.pyramid_table } '、' {z} _ {x} _ {y} ')、' hex ') " 
        result = self.poll_query(sql)
        #16進文字列の形式で返す場合のみ変換する必要がある
        result = binascii .a2b_hex(result)
        return result 

app = Flask(__ name __)

@ app.route( '/ vector')
def vector_demo():
    return send_from_directory( "./"、 "Vector.html")

#テーブル名、フィールド名、など
pngViewer = PngViewer(CONNECTION、 'usbf'、 'geom'、 'gid')

@ app.route( '/ vector / png / <int:z> / <int:x> / <int:y>') 
def vector_png(z、x、y):
    png = pngViewer.get_png(x、y、z)
    return Response(
        response = png、
        mimetype = "image / png" 

mvtViewer = MvtViewer(CONNECTION、 'points'、 'geom'、 'gid')

@ app.route( '/ vector / mvt / <int:z> / <int:x> / <int:y> ')
def vector_mvt(z、x、y):
    mvt = mvtViewer.get_mvt(x、y、z)
    return Response(
        response = mvt、
        mimetype = "application / vnd.mapbox -vector-tile " 

if __name__ ==" 
    __main __ ":app.run(port = 5000、threaded = True)

注:*読むには左右にスワイプしてください

上記のコードをVector.pyファイルとして保存しpython Vector.pyコマンドを実行してサービスを開始します。

使用する言語やフレームワークに関係なく、まったく同じ機能を実現するには、ベクターまたはラスタータイルのSQLステートメントをインターフェイスとしてカプセル化するだけでよいことをコードから推測することは難しくありません。従来の地図サービスの公開と比較して、Ganosのベクトルピラミッド関数を使用してオンライン視覚化を実現することは、より軽量で使いやすい選択肢です。

 

  • グリッドタイルについては、コードを変更することでスタイルを制御でき、柔軟性が大幅に向上します。
  • 他のサードパーティコンポーネントを導入する必要はなく、ターゲットを絞った最適化を実行する必要もありません。満足のいく応答パフォーマンスがあります。
  • ユーザーが使い慣れているプログラミング言語とフレームワークを選択でき、地理的でない実務家にとってより使いやすい複雑で専門的なパラメーター構成は必要ありません。

4.4クライアントコード

フロントエンドマップフレームワークとしてMapboxを選択して、バックエンドによって提供されるベクタータイルレイヤーとラスタータイルレイヤーを表示し、ベクタータイルレイヤーのレンダリングパラメーターを構成します。

説明の便宜上、フロントエンドコードは、ベクターとラスターの2つのレイヤーを同時に追加します。これらは、実際の使用で必要に応じて選択できます。

バックエンドコード同じファイルディレクトリにVector.htmlという名前の新しいファイルを作成し、次のコードを記述します。バックエンドサービスが開始されると、http://localhost:5000/vectorアクセスできるようになります。

<!DOCTYPE html> 
<html> 
  <head> 
    <meta charset = "UTF-8" /> 
    <title> </ title> 
    <link 
      href = "https://cdn.bootcdn.net/ajax/libs/mapbox- gl / 1.13.0 / mapbox-gl.min.css " 
      rel =" stylesheet " 
    /> 
  </ head> 
  <script src =" https://cdn.bootcdn.net/ajax/libs/mapbox-gl/1.13 0 / mapbox-gl.min.js "> </ script> 
  <script src =" https://cdn.bootcdn.net/ajax/libs/axios/0.21.0/axios.min.js "> </ script > 
  <body> 
    <div id = "map" style = "height:100vh" /> 
    <script> 
      const sources = { 
        osm:{
          タイプ: "ラスター"、
          タイル:["https://b.tile.openstreetmap.org/ {z} / {x} / {y} .png"]、
          tileSize:256、
        }、
      }; 
          constlayers 
      = [ 
        { id: "base_map"、
          type : "raster"、
          source: "osm"、
          layout:{visibility: "visible"}、
        }、
      ]; 
      const map = new mapboxgl.Map({ 
        container: "map"、
        style:{version:8、layers、sources}、
      }); 
      map.on( "load"、async()=> { 
        map.resize(); 
        
        //追加栅格瓦片数データソース
        map.addSource( "png_source"、{
          タイプ: "ラスター"、
          minzoom:1、
          タイル:
          tileSize:512、
        }); 
        //ラスタータイルレイヤーを追加
        map.addLayer({ 
          id: "png_layer"、
          type: " raster "、
          layout:{visibility: "visible"}、
          source: "png_source"、
        }); 
        
        / /ベクタータイルデータソースを追加
        map.addSource( "mvt_source"、{ 
          type: "vector"、
          minzoom:1、
          tiles:[`$ {window.location.href} / mvt / {z} / {x} / {y } `]、
          tileSize:512、
        }); 

        //ベクタータイルレイヤーを追加し、ベクタータイルにスタイルを追加します
        map.addLayer({ 
          id:" mvt_layer "、
          paint:{ 
            "円半径」:4、
            "circle-color": "#6699CC"、
            "circle-stroke-width":2、
            "circle-opacity":0.8、
            "circle-stroke-color": "#ffffff"、
            "circle-stroke-opacity": 0.9、
          }、
          タイプ: "circle"、
          ソース: "mvt_source"、
          "ソースレイヤー": "points_geom"、
        }); 
        
      }); 
    </ script> 
  </ body> 
</ html>

注:*読むには左右にスワイプしてください

 

4.5ベクタータイルの動的効果

 

2.gif

フロントエンドでさまざまな効果を調整できます。新しいレイヤーパラメータを調整した後の効果は次のとおりです。

{ 
  "circle-radius":4、
  "circle-color": "#000000"、
  "circle-stroke-width":2、
  "circle-opacity":0.3、
  "circle-stroke-color": "#003399" 、
  "circle-stroke-opacity":0.9、
}

3.gif

 

4.6グリッドタイルの動的効果

 

1111.gif

 

05PGADminとの統合

PGデータベース管理ツールPGAdminは、ベクターデータの視覚化をネイティブにサポートしますが、クイック表示テクノロジーがないため、単一のオブジェクトまたは限られた結果セットしか表示できず、大規模なスムーズでグローバルなビューを実行できません。ベクトルデータ。Ganosのベクタークイックディスプレイ機能をPGAdminと統合します。データがデータベースに保存されると、グローバルな状況をオンラインで閲覧し、データの概要をすばやく評価し、データ管理のエクスペリエンスを大幅に向上させることができます。

5.gif

 

06まとめ

この記事では、スパースベクトルピラミッドの原理と利点から始め、Ganosを使用してオンライン視覚化サービスのさまざまな機能を実装する方法を紹介し、最後に100行のコードで数億のデータを処理できる地図視覚化サービスを実現します。読者はさらに、視覚化に基づいてPG / PolarDB Ganosのサーバー側の高速クエリおよび分析機能を使用して、オブジェクト属性クエリ、空間円選択、空間分析などのより複雑な機能を実行できます。これは、Ganosによってもたらされた大規模な空間グラフィックスディスプレイアクセラレーションブラックテクノロジーによってもたらされた変換です。これは、スパースベクトルピラミッドインデックスです。

元のリンク

この記事はAlibabaCloudのオリジナルのコンテンツであり、許可なく複製することはできません。

おすすめ

転載: blog.csdn.net/xxscj/article/details/114112894