如何有效地将大型 PostGIS (PostgreSQL) table 导出到 GeoJSON 文件?
How can I efficiently export a large PostGIS (PostgreSQL) table to a GeoJSON file?
我建立了一个比较大的 PostgreSQL 数据库,主要包含地理空间数据。我目前正在尝试将一些数据导出为 GeoJSON 格式,以便我可以对其进行平铺并将其与某些地图 (Mapbox) 一起使用。
对于我正在处理的第一个数据集,我编写了一个快速脚本,该脚本使用以下 ogr2ogr
命令将数据导出为 GeoJSON 格式。
ogr2ogr -f GeoJSON \
-progress \
nhd_.json \
"PG:dbname=$PG_DB host=$PG_HOST port=$PG_PORT user=$PG_USERNAME password=$PG_PASSWORD" \
-sql "select resolution, geom from nhd_hr_"
由于导出的 GeoJSON 文件较大,我随后使用 geojsplit
将大型 GeoJSON 文件分解为较小的子文件,然后我能够使用 Mapbox tiling tool 来创建我的图块,然后为我的地图创建图层。
但是,现在我已经转向更大的数据库,我一直 运行 遇到这样的问题:在仅下载 12-15GB 的数据后,我与数据库的连接就会超时。
我最初的想法是将我的查询拆分为子查询,但我不完全确定我该怎么做。有什么方法可以改变我导出数据的方法吗?或者有没有办法让我将这个查询分解成更易于管理的块?
使用 seq
生成数字,然后更改您的查询以查询一系列 id 值。
在此示例中,我已将 </code> 更改为 <code>$suffix
,IRL 一旦您对输出感到满意,您将删除 echo
实际上 运行 命令(或者你可以 copy/paste 输出到另一个终端)。您需要将 2000
更改为安全地高于最大 ogc_fid 的值(select ogc_fid from whatever order by 1 desc limit 1
才能找到它),并且可能需要将 1000
更改为其他一些块大小,具体取决于每行有多大。不过,不要忘记更改 WHERE 子句中的 1000
。
$ seq 0 500 1500
0
500
1000
1500
$ for suffix in foo bar; do
> for each in $(seq 0 1000 2000); do
> echo ogr2ogr -f GeoJSON -progress nhd_$suffix.json "PG:dbname=$PG_DB host=$PG_HOST port=$PG_PORT user=$PG_USERNAME password=$PG_PASSWORD" \
> -sql "select resolution, geom from nhd_hr_$suffix where ogc_fid>=$each and ogc_fid < ($each + 1000)"
> done
> done
ogr2ogr -f GeoJSON -progress nhd_foo.json PG:dbname= host= port= user= password= -sql select resolution, geom from nhd_hr_foo where ogc_fid>=0 and ogc_fid < (0 + 1000)
ogr2ogr -f GeoJSON -progress nhd_foo.json PG:dbname= host= port= user= password= -sql select resolution, geom from nhd_hr_foo where ogc_fid>=1000 and ogc_fid < (1000 + 1000)
ogr2ogr -f GeoJSON -progress nhd_foo.json PG:dbname= host= port= user= password= -sql select resolution, geom from nhd_hr_foo where ogc_fid>=2000 and ogc_fid < (2000 + 1000)
ogr2ogr -f GeoJSON -progress nhd_bar.json PG:dbname= host= port= user= password= -sql select resolution, geom from nhd_hr_bar where ogc_fid>=0 and ogc_fid < (0 + 1000)
ogr2ogr -f GeoJSON -progress nhd_bar.json PG:dbname= host= port= user= password= -sql select resolution, geom from nhd_hr_bar where ogc_fid>=1000 and ogc_fid < (1000 + 1000)
ogr2ogr -f GeoJSON -progress nhd_bar.json PG:dbname= host= port= user= password= -sql select resolution, geom from nhd_hr_bar where ogc_fid>=2000 and ogc_fid < (2000 + 1000)
为了更容易 copy/paste 到您的 shell:
,这里是一行命令
for suffix in foo bar; do for each in $(seq 0 1000 2000); do echo ogr2ogr -f GeoJSON -progress nhd_$suffix.json "PG:dbname=$PG_DB host=$PG_HOST port=$PG_PORT user=$PG_USERNAME password=$PG_PASSWORD" -sql "select resolution, geom from nhd_hr_$suffix where ogc_fid>=$each and ogc_fid < ($each + 1000)"; done; done
我建立了一个比较大的 PostgreSQL 数据库,主要包含地理空间数据。我目前正在尝试将一些数据导出为 GeoJSON 格式,以便我可以对其进行平铺并将其与某些地图 (Mapbox) 一起使用。
对于我正在处理的第一个数据集,我编写了一个快速脚本,该脚本使用以下 ogr2ogr
命令将数据导出为 GeoJSON 格式。
ogr2ogr -f GeoJSON \
-progress \
nhd_.json \
"PG:dbname=$PG_DB host=$PG_HOST port=$PG_PORT user=$PG_USERNAME password=$PG_PASSWORD" \
-sql "select resolution, geom from nhd_hr_"
由于导出的 GeoJSON 文件较大,我随后使用 geojsplit
将大型 GeoJSON 文件分解为较小的子文件,然后我能够使用 Mapbox tiling tool 来创建我的图块,然后为我的地图创建图层。
但是,现在我已经转向更大的数据库,我一直 运行 遇到这样的问题:在仅下载 12-15GB 的数据后,我与数据库的连接就会超时。
我最初的想法是将我的查询拆分为子查询,但我不完全确定我该怎么做。有什么方法可以改变我导出数据的方法吗?或者有没有办法让我将这个查询分解成更易于管理的块?
使用 seq
生成数字,然后更改您的查询以查询一系列 id 值。
在此示例中,我已将 </code> 更改为 <code>$suffix
,IRL 一旦您对输出感到满意,您将删除 echo
实际上 运行 命令(或者你可以 copy/paste 输出到另一个终端)。您需要将 2000
更改为安全地高于最大 ogc_fid 的值(select ogc_fid from whatever order by 1 desc limit 1
才能找到它),并且可能需要将 1000
更改为其他一些块大小,具体取决于每行有多大。不过,不要忘记更改 WHERE 子句中的 1000
。
$ seq 0 500 1500
0
500
1000
1500
$ for suffix in foo bar; do
> for each in $(seq 0 1000 2000); do
> echo ogr2ogr -f GeoJSON -progress nhd_$suffix.json "PG:dbname=$PG_DB host=$PG_HOST port=$PG_PORT user=$PG_USERNAME password=$PG_PASSWORD" \
> -sql "select resolution, geom from nhd_hr_$suffix where ogc_fid>=$each and ogc_fid < ($each + 1000)"
> done
> done
ogr2ogr -f GeoJSON -progress nhd_foo.json PG:dbname= host= port= user= password= -sql select resolution, geom from nhd_hr_foo where ogc_fid>=0 and ogc_fid < (0 + 1000)
ogr2ogr -f GeoJSON -progress nhd_foo.json PG:dbname= host= port= user= password= -sql select resolution, geom from nhd_hr_foo where ogc_fid>=1000 and ogc_fid < (1000 + 1000)
ogr2ogr -f GeoJSON -progress nhd_foo.json PG:dbname= host= port= user= password= -sql select resolution, geom from nhd_hr_foo where ogc_fid>=2000 and ogc_fid < (2000 + 1000)
ogr2ogr -f GeoJSON -progress nhd_bar.json PG:dbname= host= port= user= password= -sql select resolution, geom from nhd_hr_bar where ogc_fid>=0 and ogc_fid < (0 + 1000)
ogr2ogr -f GeoJSON -progress nhd_bar.json PG:dbname= host= port= user= password= -sql select resolution, geom from nhd_hr_bar where ogc_fid>=1000 and ogc_fid < (1000 + 1000)
ogr2ogr -f GeoJSON -progress nhd_bar.json PG:dbname= host= port= user= password= -sql select resolution, geom from nhd_hr_bar where ogc_fid>=2000 and ogc_fid < (2000 + 1000)
为了更容易 copy/paste 到您的 shell:
,这里是一行命令for suffix in foo bar; do for each in $(seq 0 1000 2000); do echo ogr2ogr -f GeoJSON -progress nhd_$suffix.json "PG:dbname=$PG_DB host=$PG_HOST port=$PG_PORT user=$PG_USERNAME password=$PG_PASSWORD" -sql "select resolution, geom from nhd_hr_$suffix where ogc_fid>=$each and ogc_fid < ($each + 1000)"; done; done