第 3 章。PostGIS 管理

目录
3.1. 性能调优
3.1.1. 启动
3.1.2. 运行时
3.2. 配置栅格支持
3.3. 创建空间数据库
3.3.1. 使用 EXTENSION 使数据库具有空间功能
3.3.2. 不使用 EXTENSION 使数据库具有空间功能(不推荐)
3.4. 升级空间数据库
3.4.1. 软升级
3.4.2. 硬升级

3.1. 性能调优

PostGIS 性能调优与任何 PostgreSQL 工作负载的调优非常相似。唯一需要额外考虑的是,几何和栅格通常很大,因此与内存相关的优化通常对 PostGIS 的影响比其他类型的 PostgreSQL 查询更大。

有关优化 PostgreSQL 的一般详细信息,请参阅 优化您的 PostgreSQL 服务器

对于 PostgreSQL 9.4+,可以使用 ALTER SYSTEM 命令在服务器级别设置配置,而无需触碰 postgresql.confpostgresql.auto.conf

ALTER SYSTEM SET work_mem = '256MB';
-- this forces non-startup configs to take effect for new connections
SELECT pg_reload_conf();
-- show current setting value
-- use SHOW ALL to see all settings
SHOW work_mem;

除了 Postgres 设置之外,PostGIS 还有一些自定义设置,这些设置列在 第 7.24 节,“全局统一自定义变量 (GUC)” 中。

3.1.1. 启动

这些设置在 postgresql.conf 中配置

constraint_exclusion

  • 默认值:partition

  • 这通常用于表分区。默认情况下,它设置为“partition”,这对于 PostgreSQL 8.4 及更高版本来说是理想的,因为它将强制规划器仅分析继承层次结构中的表以进行约束考虑,否则不会对规划器造成惩罚。

shared_buffers

  • 默认值:PostgreSQL 9.6 中约为 128MB

  • 设置为可用 RAM 的 25% 到 40%。在 Windows 上,您可能无法设置得那么高。

max_worker_processes 此设置仅适用于 PostgreSQL 9.4+。对于 PostgreSQL 9.6+,此设置非常重要,因为它控制着并行查询可以拥有的最大进程数。

  • 默认值:8

  • 设置系统可以支持的最大后台进程数。此参数只能在服务器启动时设置。

3.1.2. 运行时

work_mem - 设置用于排序操作和复杂查询的内存大小

  • 默认值:1-4MB

  • 对于大型数据库、复杂查询和大量内存,请向上调整。

  • 对于多个并发用户或内存不足,请向下调整。

  • 如果您有大量内存和很少的开发人员

    SET work_mem TO '256MB';

maintenance_work_mem - 用于 VACUUM、CREATE INDEX 等的内存大小。

  • 默认值:16-64MB

  • 通常太低 - 会占用 I/O,在交换内存时锁定对象

  • 建议在具有大量内存的生产服务器上使用 32MB 到 1GB,但这取决于并发用户的数量。如果您有大量内存和很少的开发人员

    SET maintenance_work_mem TO '1GB';

max_parallel_workers_per_gather

此设置仅适用于 PostgreSQL 9.6+,并且仅影响 PostGIS 2.3+,因为只有 PostGIS 2.3+ 支持并行查询。如果设置为大于 0,则某些查询(例如涉及关系函数的查询,如 ST_Intersects)可以使用多个进程,并且在这样做时可以运行快两倍以上。如果您有很多处理器可以备用,您应该将此值更改为您拥有的处理器数量。还要确保将 max_worker_processes 提高到至少与该数字一样高。

  • 默认值:0

  • 设置单个 Gather 节点可以启动的工作程序的最大数量。并行工作程序取自由 max_worker_processes 建立的进程池。请注意,请求的工作程序数量可能在运行时不可用。如果发生这种情况,计划将使用比预期更少的工作程序运行,这可能效率低下。将此值设置为 0(默认值)将禁用并行查询执行。

3.2. 配置光栅支持

如果您启用了光栅支持,您可能需要阅读以下内容,了解如何正确配置它。

从 PostGIS 2.1.3 开始,默认情况下禁用数据库外光栅和所有光栅驱动程序。为了重新启用这些,您需要在服务器环境中设置以下环境变量 POSTGIS_GDAL_ENABLED_DRIVERSPOSTGIS_ENABLE_OUTDB_RASTERS。对于 PostGIS 2.2,您可以使用更跨平台的方法来设置相应的 第 7.24 节,“Grand Unified Custom Variables (GUCs)”

如果您想启用离线光栅

POSTGIS_ENABLE_OUTDB_RASTERS=1

任何其他设置或根本没有设置都将禁用数据库外光栅。

为了启用 GDAL 安装中可用的所有 GDAL 驱动程序,请按如下方式设置此环境变量

POSTGIS_GDAL_ENABLED_DRIVERS=ENABLE_ALL

如果您只想启用特定驱动程序,请按如下方式设置环境变量

POSTGIS_GDAL_ENABLED_DRIVERS="GTiff PNG JPEG GIF XYZ"
[Note]

如果您使用的是 Windows,请不要引用驱动程序列表。

设置环境变量取决于操作系统。对于通过 apt-postgresql 在 Ubuntu 或 Debian 上安装的 PostgreSQL,首选方法是编辑 /etc/postgresql/10/main/environment,其中 10 指的是 PostgreSQL 的版本,main 指的是集群。

在 Windows 上,如果您以服务形式运行,则可以通过系统变量进行设置,对于 Windows 7,您可以通过右键单击“计算机”->“属性”->“高级系统设置”或在资源管理器中导航到 控制面板\所有控制面板项\系统 来访问。然后单击 高级系统设置 ->高级 ->环境变量 并添加新的系统变量。

设置完环境变量后,您需要重新启动 PostgreSQL 服务才能使更改生效。

3.3. 创建空间数据库

3.3.1. 使用 EXTENSION 使数据库具有空间功能

如果您使用的是 PostgreSQL 9.1+ 并且已经编译并安装了 extensions/postgis 模块,您可以使用 EXTENSION 机制将数据库转换为空间数据库。

核心 postgis 扩展包括 geometry、geography、spatial_ref_sys 以及所有函数和注释。栅格和拓扑作为单独的扩展进行打包。

在您要启用空间功能的数据库中运行以下 SQL 代码段

      CREATE EXTENSION IF NOT EXISTS plpgsql;
      CREATE EXTENSION postgis;
      CREATE EXTENSION postgis_raster; -- OPTIONAL
      CREATE EXTENSION postgis_topology; -- OPTIONAL

3.3.2. 不使用 EXTENSION 使数据库具有空间功能(不推荐)

[Note]

这通常仅在您无法或不想将 PostGIS 安装在 PostgreSQL 扩展目录中时才需要(例如在测试、开发或受限环境中)。

通过加载构建阶段指定的 [prefix]/share/contrib 中的各种 sql 文件,将 PostGIS 对象和函数定义添加到您的数据库中。

核心 PostGIS 对象(geometry 和 geography 类型及其支持函数)位于 postgis.sql 脚本中。栅格对象位于 rtpostgis.sql 脚本中。拓扑对象位于 topology.sql 脚本中。

对于完整的 EPSG 坐标系定义标识符集,您还可以加载 spatial_ref_sys.sql 定义文件并填充 spatial_ref_sys 表。这将允许您对几何体执行 ST_Transform() 操作。

如果您希望向 PostGIS 函数添加注释,您可以在 postgis_comments.sql 脚本中找到它们。可以通过在 psql 终端窗口中简单地键入 \dd [function_name] 来查看注释。

在您的终端中运行以下 Shell 命令

    DB=[yourdatabase]
    SCRIPTSDIR=`pg_config --sharedir`/contrib/postgis-3.3/

    # Core objects
    psql -d ${DB} -f ${SCRIPTSDIR}/postgis.sql
    psql -d ${DB} -f ${SCRIPTSDIR}/spatial_ref_sys.sql
    psql -d ${DB} -f ${SCRIPTSDIR}/postgis_comments.sql # OPTIONAL

    # Raster support (OPTIONAL)
    psql -d ${DB} -f ${SCRIPTSDIR}/rtpostgis.sql
    psql -d ${DB} -f ${SCRIPTSDIR}/raster_comments.sql # OPTIONAL

    # Topology support (OPTIONAL)
    psql -d ${DB} -f ${SCRIPTSDIR}/topology.sql
    psql -d ${DB} -f ${SCRIPTSDIR}/topology_comments.sql # OPTIONAL

3.4. 升级空间数据库

升级现有的空间数据库可能很棘手,因为它需要替换或引入新的 PostGIS 对象定义。

不幸的是,并非所有定义都可以在实时数据库中轻松替换,因此有时您最好的选择是转储/重新加载过程。

PostGIS 为次要或错误修复版本提供 SOFT UPGRADE 过程,为主要版本提供 HARD UPGRADE 过程。

在尝试升级 PostGIS 之前,始终值得备份您的数据。如果您使用 -Fc 标志到 pg_dump,您将始终能够使用 HARD UPGRADE 恢复转储。

3.4.1. 软升级

如果您使用扩展安装了数据库,则也需要使用扩展模型进行升级。如果您使用旧的 sql 脚本方式安装,建议您将安装切换到扩展,因为脚本方式不再受支持。

3.4.1.1. 使用扩展的 9.1+ 软升级

如果您最初使用扩展安装了 PostGIS,那么您也需要使用扩展进行升级。使用扩展进行次要升级非常轻松。

如果您运行的是 PostGIS 3 或更高版本,则应使用 PostGIS_Extensions_Upgrade 函数升级到您已安装的最新版本。

SELECT postgis_extensions_upgrade();

如果您运行的是 PostGIS 2.5 或更低版本,请执行以下操作

ALTER EXTENSION postgis UPDATE;
SELECT postgis_extensions_upgrade();
-- This second call is needed to rebundle postgis_raster extension
SELECT postgis_extensions_upgrade();

如果您安装了多个版本的 PostGIS,并且您不想升级到最新版本,您可以显式指定版本,如下所示

ALTER EXTENSION postgis UPDATE TO "3.4.3dev";
ALTER EXTENSION postgis_topology UPDATE TO "3.4.3dev";

如果您收到类似以下的错误通知

No migration path defined for … to 3.4.3dev

那么您需要备份您的数据库,创建一个新的数据库,如 第 3.3.1 节,“使用 EXTENSION 使数据库具有空间功能” 中所述,然后将您的备份恢复到这个新数据库上。

如果您收到类似以下的通知消息

Version "3.4.3dev" of extension "postgis" is already installed

那么一切都已更新,您可以安全地忽略它。 除非 您尝试从开发版本升级到下一个版本(没有新的版本号);在这种情况下,您可以将“next”附加到版本字符串,下次您需要再次删除“next”后缀

ALTER EXTENSION postgis UPDATE TO "3.4.3devnext";
ALTER EXTENSION postgis_topology UPDATE TO "3.4.3devnext";
[Note]

如果您最初安装 PostGIS 时没有指定版本,您通常可以在恢复之前跳过 postgis 扩展的重新安装,因为备份中只有 CREATE EXTENSION postgis,因此在恢复期间会选择最新的最新版本。

[Note]

如果您从 3.0.0 之前的版本升级 PostGIS 扩展,您将有一个新的扩展 postgis_raster,如果您不需要栅格支持,可以安全地删除它。您可以按如下方式删除

DROP EXTENSION postgis_raster;

3.4.1.2. 9.1+ 之前或无扩展的软升级

本节仅适用于那些未使用扩展安装 PostGIS 的用户。如果您有扩展并尝试使用此方法升级,您将收到类似的消息

can't drop … because postgis extension depends on it

注意:如果您从 PostGIS 1.* 迁移到 PostGIS 2.* 或从 r7409 之前的 PostGIS 2.* 迁移,则无法使用此过程,而是需要进行 硬升级

编译和安装(make install)后,您应该在安装文件夹中找到一组 *_upgrade.sql 文件。您可以使用以下命令列出所有文件:

ls `pg_config --sharedir`/contrib/postgis-3.4.3dev/*_upgrade.sql

依次加载所有文件,从 postgis_upgrade.sql 开始。

psql -f postgis_upgrade.sql -d your_spatial_database

相同过程适用于栅格、拓扑和 sfcgal 扩展,升级文件分别命名为 rtpostgis_upgrade.sqltopology_upgrade.sqlsfcgal_upgrade.sql。如果您需要它们

psql -f rtpostgis_upgrade.sql -d your_spatial_database
psql -f topology_upgrade.sql -d your_spatial_database
psql -f sfcgal_upgrade.sql -d your_spatial_database

建议您通过运行以下命令切换到基于扩展的安装

psql -c "SELECT postgis_extensions_upgrade();"
[Note]

如果您找不到用于升级您正在使用的版本的 postgis_upgrade.sql,则您使用的版本过早,无法进行软升级,需要进行 硬升级

PostGIS_Full_Version 函数应通过“procs need upgrade”消息通知您是否需要运行此类升级。

3.4.2. 硬升级

硬升级是指对启用 PostGIS 的数据库进行完全的转储/重新加载。当 PostGIS 对象的内部存储发生更改或无法进行软升级时,您需要进行硬升级。 发行说明 附录报告每个版本是否需要转储/重新加载(硬升级)以进行升级。

转储/重新加载过程由 postgis_restore 脚本辅助,该脚本负责跳过转储中属于 PostGIS 的所有定义(包括旧的定义),允许您将模式和数据还原到已安装 PostGIS 的数据库中,而不会出现重复符号错误或将已弃用的对象带回。

Windows 用户的补充说明可在 Windows 硬升级 中找到。

过程如下

  1. 创建一个“自定义格式”的数据库转储,您要升级的数据库(我们称之为 olddb),包括二进制 Blob (-b) 和详细 (-v) 输出。用户可以是数据库的拥有者,不需要是 postgres 超级帐户。

    pg_dump -h localhost -p 5432 -U postgres -Fc -b -v -f "/somepath/olddb.backup" olddb
  2. 在新的数据库中全新安装 PostGIS - 我们将此数据库称为 newdb。请参考 第 3.3.2 节,“使用 EXTENSION(不推荐)启用空间数据库”第 3.3.1 节,“使用 EXTENSION 启用空间数据库” 获取有关如何执行此操作的说明。

    您转储中找到的 spatial_ref_sys 条目将被恢复,但它们不会覆盖 spatial_ref_sys 中现有的条目。这是为了确保官方集中修复能够正确传播到已恢复的数据库。如果出于任何原因,您确实想要自己覆盖标准条目,只需在创建新数据库时不要加载 spatial_ref_sys.sql 文件即可。

    如果您的数据库非常旧,或者您知道您一直在视图和函数中使用长期弃用的函数,您可能需要加载 legacy.sql 以便所有函数、视图等都能正确恢复。仅在 _确实_ 需要时才执行此操作。如果可能,请考虑在转储之前升级您的视图和函数。弃用的函数可以通过加载 uninstall_legacy.sql 稍后删除。

  3. 使用 postgis_restore 将您的备份恢复到新的 newdb 数据库中。如果出现任何意外错误,psql 将将其打印到标准错误流。记录这些错误。

    postgis_restore "/somepath/olddb.backup" | psql -h localhost -p 5432 -U postgres newdb 2> errors.txt

在以下情况下可能会出现错误

  1. 您的某些视图或函数使用了弃用的 PostGIS 对象。为了解决这个问题,您可以尝试在恢复之前加载 legacy.sql 脚本,或者您必须恢复到仍然包含这些对象的 PostGIS 版本,并在移植代码后再次尝试迁移。如果 legacy.sql 方法对您有效,请不要忘记修复您的代码以停止使用弃用的函数,并通过加载 uninstall_legacy.sql 删除它们。

  2. 转储文件中一些自定义的 spatial_ref_sys 记录具有无效的 SRID 值。有效的 SRID 值大于 0 且小于 999000。999000.999999 范围内的值保留供内部使用,而大于 999999 的值则完全无法使用。所有具有无效 SRID 的自定义记录将被保留,其中大于 999999 的记录将被移至保留范围,但 spatial_ref_sys 表将丢失一个用于保护该不变式成立的检查约束,并且可能还会丢失其主键(当多个无效 SRID 被转换为相同的保留 SRID 值时)。

    为了解决这个问题,您应该将自定义 SRS 复制到具有有效值的 SRID(可能在 910000..910999 范围内),将所有表转换为新的 SRID(参见 UpdateGeometrySRID),从 spatial_ref_sys 中删除无效条目,并使用以下命令重新构建检查约束:

    ALTER TABLE spatial_ref_sys ADD CONSTRAINT spatial_ref_sys_srid_check check (srid > 0 AND srid < 999000 );
        
    ALTER TABLE spatial_ref_sys ADD PRIMARY KEY(srid));
        

    如果您正在升级包含法国 IGN 地图的旧数据库,您可能会有超出范围的 SRID,并且在导入数据库时会看到类似以下问题

     WARNING: SRID 310642222 converted to 999175 (in reserved zone)

    在这种情况下,您可以尝试以下步骤:首先,从 postgis_restore 生成的 SQL 中完全删除 IGN。因此,在运行

    postgis_restore "/somepath/olddb.backup" > olddb.sql

    运行以下命令

    grep -v IGNF olddb.sql > olddb-without-IGN.sql

    然后创建您的新数据库,激活所需的 Postgis 扩展,并使用以下命令正确插入法国系统 IGN: 此脚本 这些操作完成后,导入您的数据

    psql -h localhost -p 5432 -U postgres -d newdb -f olddb-without-IGN.sql  2> errors.txt