GanosBaseへのベクターデータとラスターデータのインポートのベストプラクティス

> 本記事は[こちらのブログ](https://www.alibabacloud.com/blog/best-practices-for-importing-vector-and-raster-data-to-ganosbase_601841?spm=a2c65.11461433.0.0.4ee35355mzU0fa)を参考にしています。
> 翻訳にはアリババクラウドの[ModelStudio](https://www.alibabacloud.com/en/product/modelstudio)([Qwen](https://www.alibabacloud.com/en/solutions/generative-ai/qwen))を使用しております。

ベクトルデータとラスター データは、様々な産業界で広く使用される GIS アプリケーションの主要な空間データ型です。GanosBase は、これらのデータ型の両方に対して強力な処理能力を提供しています。アリババクラウドの <a href=https://www.alibabacloud.com/product/polardb-for-postgresql target=_blank>PolarDB for PostgreSQL</a> の弾性的な並列処理機能に基づいて、GanosBase は従来の解決策よりも著しく高い計算効率を実現しています。この記事では、GanosBase へのベクトルおよびラスター データの効率的な取り込み方法について概要を説明します。クラウドネイティブ データベースへの空間データの取り込みソリューションを理解することで、GanosBase のベクトルおよびラスター データの処理能力をより効果的に活用できます。

### 背景
PostgreSQL コミュニティ版の PostGIS では、ベクトルおよびラスター データの高速取り込みに `shp2pgsql` と `raster2pgsql` のコマンドラインツールが提供されています。これらのツールを使用する際には、取り込むデータの SRID、ファイルエンコーディング、テーブル名、取り込み方法を指定する必要があります。ラスター データを取り込む場合、ラスターのバンドやタイル サイズなどのパラメーターも指定する必要があります。しかし、これらの方法は PolarDB データベースへのデータ取り込みには適しておらず、以下の理由から：

- PostGIS が提供する取り込みツールは、データベースをホストするサーバーに対する完全な制御を必要とするが、PolarDB は共有ストレージアーキテクチャを使用しており、ローカルディスクを提供しません。また、PolarDB データベースは基盤となるサーバーリソースの弾性性を利用しており、ホスト情報の提供はできません。
- PostGIS Raster と GanosBase Raster は異なるストレージ構造を使用しており、GanosBase はクラウドネイティブの分散ストレージサービスである <a href=https://www.alibabacloud.com/product/object-storage-service?spm=a2c63.p38356.6791778070.406.5fba4977v14Lrh target=_blank>オブジェクトストレージサービス（OSS）</a> を使用して、ベクトルおよびラスター データの取り込み向けの使いやすい関数レベルのツールを提供しています。

### データ取り込み方法

#### ベクトルデータの取り込み

#### GIS デスクトップツールを使用したデータ取り込み
<a href=https://www.alibabacloud.com/product/polardb-for-postgresql?spm=a3c0i.14509290.7580098850.5.45d47b8dW1n5QI target=_blank>PolarDB for PostgreSQL</a> は PostgreSQL コミュニティ版と完全互換であり、QGISなどのGISデスクトップツールを使用してベクトルデータを取り込むことができます。PostgreSQLデータソース接続を作成し、PolarDBデータベースに接続し、デスクトップツールのデータ取り込み機能を使用してデータを取り込むことができます。

#### FDW（外部データラッパー）を使用したデータ取り込み
外部データラッパー（FDW）は、同じクラスタ内の他のデータベースや他のインスタンスにある外部データにアクセスするために使用される PostgreSQL 拡張機能です。ベクトルデータの取り込みには、GanosBase FDW の使用が推奨されます。これは様々な空間データへの統一アクセスをサポートし、幾何学的空间データ型を自動的に `Geometry` 型にマッピングすることができます。FDW を使用して外部テーブルとクラスタ内のテーブルを一元化された方法でアクセスおよび照会することができます。例えば、OSSに格納されている `poly.shp` ファイルを GanosBase 内の `Geometry` 型のデータを含むテーブルとして取り込むには、以下の手順を実行します：

1. 拡張機能をインストールする。
   ```
   CREATE EXTENSION ganos_spatialref;
   CREATE EXTENSION ganos_geometry;
   CREATE EXTENSION ganos_fdw;
   ```

2. `ST_ForeignTables` 関数を使用して、`poly.shp` スペースデータファイルを外部テーブルとして登録する。
   ```
   SELECT ST_RegForeignTables(OSS://<ak_id>:<ak_secret>@<endpoint>/path/poly.shp);
   ```

3. `information_schema.foreign_tables` ビューを使用して、登録された FDW テーブル `poly` を照会する。
   ```
   SELECT foreign_table_name FROM information_schema.foreign_tables 
     ORDER BY foreign_table_name ASC;
   ```

**注意**: 上記の手順では、外部テーブル内の外部データはデータマッピングを通じて照会されますが、データベースに書き込まれることはありません。外部テーブルのデータを使用してテーブルを作成するには、以下のステートメントを実行します：
```
CREATE TABLE poly_db AS SELECT * FROM poly;
```

#### ラスター データの取り込み

GanosBase は、外部ラスター データをデータベースに取り込むための `ST_ImportFrom` と `ST_CreateRast` 関数を提供しています。どちらの関数も、外部ラスター データに基づいて `Raster` 型のオブジェクトを作成し、イメージのメタデータを保存します。`ST_ImportFrom` 関数は、さらにイメージ データをデフォルトで 256x256 ピクセルの正規サイズのチャンクに分割し、`chunkTableName` パラメーターの値に基づいてデータベースに保存します。一方、`ST_CreateRast` 関数は `Raster` オブジェクトのみを作成し、ピクセル データをデータベースに取り込むことはありません。

#### TIFF データの取り込み

TIFF は一般的なラスター データ形式です。以下は、OSSからGanosBaseにTIFFデータを取り込む例です。

1. OSSにTIFFデータを準備する。
2. TIFFデータを格納するための `Raster` フィールドを持つテーブルを作成する。
   ```
   CREATE TABLE raster_table
   (
     id integer,
     format text,
     rast raster
   );
   ```

3. TIFFデータを以下のように取り込む。
   ```
   INSERT INTO raster_table
   SELECT 1, 'TIFF', ST_ImportFrom(chunk_table,OSS://<ak>:<ak_secret>@oss-cn-beijing-internal.aliyuncs.com/mybucket/data/G50E009001DOM.tif);

   INSERT INTO raster_table
   SELECT 2, 'TIFF', ST_CreateRast(OSS://<ak>:<ak_secret>@oss-cn-beijing-internal.aliyuncs.com/mybucket/data/G50E009001DOM.tif);
   ```

4. 結果として、それぞれの方法により `Raster` オブジェクトが生成され、GanosBase が提供するラスターリaltedのUDFを使用してこれらの `Raster` オブジェクトに対して操作を行うことができます。
   ```
   SELECT id,ST_Georeference(rast),st_extent(rast),ST_NumBands(rast),ST_SRID(rast),st_value(rast,0,100,100),st_value(rast,1,200,200) FROM raster_table;
   ```

#### HDF5/NetCDF データの取り込み

HDF5とNetCDFも一般的なラスター データ形式であり、地球観測、科学計算、気象や海洋学などの地学分野でよく使用されます。これらも `ST_ImportFrom` と `ST_CreateRast` 関数を使用して取り込むことができます。TIFFデータの取り込みにおけるSQL文と似ています。
```
INSERT INTO raster_table
SELECT 3, 'NC', ST_ImportFrom(chunk_table,OSS://<ak>:<ak_secret>@oss-cn-beijing-internal.aliyuncs.com/dmybucket/data/Z_NAFP_C_BABJ_20210430000556_P_HRCLDAS_RT_CHN_0P01_HOR-WIV-2021043000.nc);

INSERT INTO raster_table
SELECT 4, 'NC', ST_CreateRast(OSS://<ak>:<ak_secret>@oss-cn
以下はサンプルステートメントです：

- NetCDFファイルの場合:
```sql
INSERT INTO raster_table
SELECT 5, NC, ST_ImportFrom(chunk_table, 'OSS://<ak>:<ak_secret>@oss-cn-beijing-internal.aliyuncs.com/dmybucket/data/image.nc:sub_name');
```

- HDF5ファイルの場合:
```sql
INSERT INTO raster_table
SELECT 5, HDF5, ST_ImportFrom(chunk_table, 'OSS://<ak>:<ak_secret>@oss-cn-beijing-internal.aliyuncs.com/dmybucket/data/image.hdf5://path/sub_name');
```
HDF5とNetCDFファイルが3次元以上の場合は、`chunkdim`パラメータも指定する必要があります。データベースに読み込まれたラスター情報は(w, h, b)の次元でロード・保存されます。ここでwはチャンクの幅、hはチャンクの高さ、bはバンド数を表します。3次元以上のNetCDFファイルの場合、xおよびy座標以外のすべての次元のバンド数の積がチャンクのバンド数として保存されます。例えば次のNetCDFファイルでは、lonとlatの他にtimeとisobaricという次元があります。ST_ImportFromを使用してデータをインポートする際に、latとlon以外のすべての次元のバンド数の積をchunkdimのバンド数として指定します。この例では、バンド数は120となります。以下のようなSQL文になります：
```sql
INSERT INTO nc_table VALUES(1, ST_ImportFrom(nc_rbt, '/Users/xiaofei/Data/raster/nc_demo.nc',{chunkdim:(256,256,120)}));
```
バッチデータのインポート
OSSからのバッチデータインポートを行うには、スクリプトが必要です。以下のPythonのサンプルコードは、OSSからデータベースへのラスターデータの一括インポート方法を示しています：
**注**: スクリプトを実行する前に、Pythonが初期化されていることを確認してください。

```python
## 必要なライブラリのインポート
import oss2
import psycopg2
import logging

## OSSへの接続
auth = oss2.Auth(AK_ID, AK_Secret)
bucket = oss2.Bucket(auth, '***endpoint***', '***bucket_name***')

## データベースへの接続とカーソルの取得
con = psycopg2.connect(database='***dataq***', user='***dde***',
                      options='-c search_path=aster,public',  # スキーマ
                      password='******', host='******', port='******')

cur = con.cursor()

## データインポート用のSQLステートメント
insert_sql = 'INSERT INTO {raster_table_name}(filename, band_index, raster_obj) VALUES ...'

## OSSからすべてのHDF5ファイル名を取得し、ファイル名を保存
with open('upload.txt', 'a', encoding='utf-8') as ff:
    for obj in oss2.ObjectIterator(bucket, prefix='...'):
        filename = obj.key.split('/')[-1]
        if filename.find('.hdf5') == -1:
            continue
        else:
            ff.write(filename + '\n')

## ファイルリストの取得
fileList = []
with open('upload.txt', 'r') as f:
    fileList = f.read().split('\n')

## ファイルリストを走査し、SQL生成、データインポート
for file in fileList:
    # insert_sqlを編集し、パラメータを追加...

    # データのインポート:
    try:
        cur.execute(insert_sql)
        con.commit()
        logging.info(filename + ' finished')
    except (Exception, psycopg2.Error) as e:
        logging.info(filename + ' error!') 
        print(filename + ' upload failed\n')
```
結論
[PolarDB](https://www.alibabacloud.com/product/polardb?spm=a3c0i.27899667.6791778070.495.12286732CLj0um)は、独自のデータ書き込み方法を提供します。GanosBaseが提供する機能レベルのインポートツールは、SQLレベルでのデータインポート、問い合わせ、分析、サービス能力を統合し、異なるビジネス段階で一貫性のあるデータ操作を可能にすることで、標準化されたワークフローの構築と利便性の向上を支援します。