PostgreSQL初探

1. 简介

PostgreSQL是以加州大学伯克利分校计算机系开发的 POSTGRES, Version 4.2为基础的对象关系型数据库管理系统(ORDBMS)。POSTGRES开创的许多概念在很久以后才出现在商业数据库中。

PostgreSQL支持大部分SQL标准并且提供了许多其它现代特性:

  • 复杂查询
  • 外键
  • 触发器
  • 可更新的视图
  • 事务完整性
  • 多版本并发控制

另外,PostgreSQL可以用许多方法进行扩展,比如通过增加新的:

  • 数据类型
  • 函数
  • 操作符
  • 聚合函数
  • 索引方法
  • 过程语言

经过二十几年的发展,PostgreSQL 是目前世界上最先进的开源数据库系统。

2. 体系基本概念

PostgreSQL使用常见的客户端/服务器 的模式。一次PostgreSQL会话由下列相关的进程(程序)组成:

  • 服务器进程

    它管理数据库文件,接受来自客户端应用与数据库的连接,并且代表客 户端在数据库上执行操作。数据库服务器程序叫postgres。

  • 客户端应用

    客户端应用可能本身就是多种多样的:它们可以是一个字符界面的工具,也可以是一个图形界面的应用, 或者是一个通过访问数据库来显示网页的 web 服务器,或者是一个特殊的数据库管理工具。一些客户端应用是和PostgreSQL发布一起提供的,但绝大部分是用户开发的。

PostgreSQL服务器可以处理来自客户端的多个并发连接。 因此,它为每个连接启动(“forks”)一个新的进程。从这个时候开始,客户端和新服务器进程就不再经过最初的postgres进程进行通讯。因此,主服务器总是在运行,等待客户端连接,而客户端及其相关联的服务器进程则是起起停停。

3. 基本使用

3.1 常用命令

\l 列出所有数据库   或者: SELECT datname FROM pg_database;
\du 列出所有角色/用户 或者: SELECT rolname FROM pg_roles;
\q 退出数据库
\d 列出当前数据库里的所有表
\dt 列出当前数据库里的所有资料表
\c dbname 切换数据库
\dx 显示安装的插件
\x 切换横向竖向显示
show <参数名> 查看该参数的值

3.2 建表

CREATE TABLE weather (
    city            varchar(80),
    temp_lo         int,           -- low temperature
    temp_hi         int,           -- high temperature
    prcp            real,          -- precipitation
    date            date
);

3.3 从文本加载数据

先在/tmp下创建mydb.txt,内容如下:

'shanghai' 20 30 0.07 '2011-11-11'
'chengdu' 2 45 0.9 '2008-09-08'
'shanghai' 20 30 0.07 '2011-11-11'
'chengdu' 2 45 0.9 '2008-09-08'

将mydb.txt里的内容导入weather表中:

COPY weather FROM '/tmp/mydb.txt' delimiter ' ';  --delimiter指定分隔符,txt文件默认分隔符是'\t',CSV文件默认分隔符是','

此时查看weather表中的数据:

select * from weather;

结果:

mydb=# select * from weather;
    city    | tmp_lo | tmp_hi | prcp |    date
------------+--------+--------+------+------------
 'shanghai' |     20 |     30 | 0.07 | 2011-11-11
 'chengdu'  |      2 |     45 |  0.9 | 2008-09-08
 'shanghai' |     20 |     30 | 0.07 | 2011-11-11
 'chengdu'  |      2 |     45 |  0.9 | 2008-09-08
(4 行记录)

4. 单机部署

在192.168.20.93和192.168.20.94上分别部署了单机版的PostgreSQL。

4.1 安装PostgreSQL源

rpm -Uvh http://yum.postgresql.org/9.4/redhat/rhel-7-x86_64/pgdg-centos94-9.4-1.noarch.rpm

4.2 执行安装命令

yum update
yum install postgresql94-server postgresql94-contrib

4.3 验证是否安装成功

执行:

rpm -qa | grep postgres

结果:

postgresql94-9.4.10-1PGDG.rhel7.x86_64
postgresql94-server-9.4.10-1PGDG.rhel7.x86_64
postgresql94-libs-9.4.10-1PGDG.rhel7.x86_64
postgresql94-contrib-9.4.10-1PGDG.rhel7.x86_64

说明安装成功

4.4 初始化数据库

先创建数据存放目录:

mkdir -p /opt/pgsql/data

赋予postgres用户该目录的权限:

chown postgres /opt/pgsql/data

切换到postgres用户:

su postgres

执行初始化:

initdb -D /opt/pgsql/data

注:

-D 后面是数据库文件存放的目录,如果不指定则默认在/var/lib/pgsql/9.4/data下

初始化的日志如下:

属于此数据库系统的文件宿主为用户 "postgres".
此用户也必须为服务器进程的宿主.
数据库簇将使用本地化语言 "zh_CN.UTF-8"进行初始化.
默认的数据库编码已经相应的设置为 "UTF8".
initdb: 无法为本地化语言环境"zh_CN.UTF-8"找到合适的文本搜索配置
缺省的文本搜索配置将会被设置到"simple"

禁止为数据页生成校验和.

修复已存在目录 /opt/pgsql/data 的权限 ... 成功
正在创建子目录 ... 成功
选择默认最大联接数 (max_connections) ... 100
选择默认共享缓冲区大小 (shared_buffers) ... 128MB
选择动态共享内存实现 ......posix
创建配置文件 ... 成功
在 /opt/pgsql/data/base/1 中创建 template1 数据库 ... 成功
初始化 pg_authid ...  成功
初始化dependencies ... 成功
创建系统视图 ... 成功
正在加载系统对象描述 ...成功
创建(字符集)校对规则 ... 成功
创建字符集转换 ... 成功
正在创建字典 ... 成功
对内建对象设置权限 ... 成功
创建信息模式 ... 成功
正在装载PL/pgSQL服务器端编程语言...成功
清理数据库 template1 ... 成功
拷贝 template1 到 template0 ... 成功
拷贝 template1 到 template0 ... 成功
同步数据到磁盘...成功

成功. 您现在可以用下面的命令运行数据库服务器:

    /usr/pgsql-9.4/bin/postmaster -D /opt/pgsql/data/
或者
    /usr/pgsql-9.4/bin/pg_ctl -D /opt/pgsql/data/ -l logfile start

4.5 启动服务

1.切换到postgres用户

su postgres

因为启动服务同样必须以PostgreSQL用户帐户登录来做。

2.启动服务

没有-D选项,服务器将使用环境变量PGDATA命名的目录; 如果这个环境变量也没有,将导致失败。通常,最好在后台启动postgres,使用下面的 Unix shell 语法:

pg_ctl -D /opt/pgsql/data/ -l logfile start

3.设置开机自动启动

在Linux系统里,要么往/etc/rc.d/rc.local或 /etc/rc.local文件里加上下面几行:

/usr/local/pgsql/bin/pg_ctl start -l logfile -D /usr/local/pgsql/data

4.6 创建用户

PostgreSQL使用角色的概念管理数据库访问权限。 根据角色自身的设置不同,一个角色可以看做是一个数据库用户,或者一组数据库用户。 角色可以拥有数据库对象(比如表)以及可以把这些对象上的权限赋予其它角色, 以控制谁拥有访问哪些对象的权限。另外,我们也可以把一个角色的成员 权限赋予其它角色,这样就允许成员角色使用分配给另一个角色的权限。
角色的概念替换了”用户”和”组”。在PostgreSQL 版本 8.1 之前,用户和组是独立类型的记录,但现在它们只是角色。 任何角色都可以是一个用户、一个组、或者两者。

数据库角色从概念上与操作系统用户是完全无关的。在实际使用中把它们对应起来可能比较方便, 但这不是必须的。数据库角色在整个数据库集群中是全局的(而不是每个库不同)。 要创建一个角色,使用 SQL 命令CREATE ROLE执行:

CREATE ROLE name;

name遵循 SQL 标识的规则:要么完全没有特殊字符, 要么用双引号包围(实际上你通常会给命令增加额外的选项,比如LOGIN。 下面显示更多细节)。要删除一个现有角色,使用类似的DROP ROLE命令:

DROP ROLE name;

为了方便,程序createuserdropuser 提供了对了这些 SQL 命令的封装。我们可以在 shell 命令上直接调用它们:

直接在shell里输入:

createuser lbd;

这样就创建了lbd这个角色。

dropuser lbd;

这样就创建了lbd这个角色。

要检查现有角色的集合,可以检查pg_roles系统表,比如:

SELECT rolname FROM pg_roles;

结果如下:

postgres=# SELECT rolname FROM pg_roles;
 rolname
----------
 postgres
 lbd
(2 行记录)

psql的元命令\du
也可以用于列出现有角色。

结果如下:

postgres=# \du
                        角色列表
 角色名称 |               属性                | 成员属于
---------+----------------------------------+----------
 lbd     |                                   | {}
 postgres| 超级用户, 建立角色, 建立 DB, 复制     | {}

5. 主从流复制部署

192.168.20.93上部署主服务器,192.168.20.94上部署从服务器。

5.1 简介

postgres在9.0之后引入了主从的流复制机制,所谓流复制,就是从服务器通过tcp流从主服务器中同步相应的数据。这样当主服务器数据丢失时从服务器中仍有备份。

与基于文件日志传送相比,流复制允许保持从服务器更新。 从服务器连接主服务器,其产生的流WAL记录到从服务器, 而不需要等待主服务器写完WAL文件。

PostgreSQL流复制默认是异步的。在主服务器上提交事务和从服务器上变化可见之间有一个小的延迟,这个延迟远小于基于文件日志传送,通常1秒能完成。如果主服务器突然崩溃,可能会有少量数据丢失。

同步复制必须等主服务器和从服务器都写完WAL后才能提交事务。这样在一定程度上会增加事务的响应时间。

配置同步复制仅需要一个额外的配置步骤: synchronous_standby_names必须设置为一个非空值。synchronous_commit也必须设置为on。

这里部署的是异步的流复制。

注:
主从服务器所在节点的系统、环境�等最好一致。PostgreSQL版本也最好一致,否则可能会有问题。

5.2 安装部署

先在192.168.20.93和192.168.20.94均安装PostgreSQL。

具体安装部署步骤见上一节:单机部署

5.2.1 主服务器

主服务器为192.168.20.93

先创建一个新目录:

mkdir /opt/pgsql/pg_archive

1.首先需要创建一个数据库用户进行主从同步。创建用户replica,并赋予登录和复制的权限。

postgres# CREATE ROLE replica login replication encrypted password 'replica'

2.修改pg_hba.conf,允许replica用户来同步。

在pg_hba.conf里增加两行:

host     all             all          192.168.20.94/32          trust   #允许94连接到主服务器
host   replication      replica       192.168.20.94/32          md5   #允许94使用replica用户来复制

这样,就设置了replica这个用户可以从192.168.20.93进行流复制请求。

注:
第二个字段必须要填replication

4.修改postgresql.conf

listen_addresses = '*'   # 监听所有IP
archive_mode = on  # 允许归档
archive_command = 'cp %p /opt/pgsql/pg_archive/%f'  # 用该命令来归档logfile segment
wal_level = hot_standby 
max_wal_senders = 32 # 这个设置了可以最多有几个流复制连接,差不多有几个从,就设置几个
wal_keep_segments = 256 # 设置流复制保留的最多的xlog数目
wal_sender_timeout = 60s # 设置流复制主机发送数据的超时时间
max_connections = 100 # 这个设置要注意下,从库的max_connections必须要大于主库的

配置完两个文件后重启服务器。

pg_ctl stop -D /opt/pgsql/data
pg_ctl start -D /opt/pgsql/data

3.测试94能否连接93数据库。在94上运行如下命令:

psql -h 192.168.20.93 -U postgres

看看是否能进入数据库。若可以,则正常。

5.2.2 从服务器

1.从主节点拷贝数据到从节点

su - postgres
rm -rf /opt/pgsql/data/*   #先将data目录下的数据都清空
pg_basebackup -h 192.168.20.93 -U replica -D /opt/pgsql/data -X stream -P  # 从93拷贝数据到94(基础备份)
mkdir /opt/pgsql/pg_archive

2.配置recovery.conf

复制/usr/pgsql-9.4/share/recovery.conf.sample 到 /opt/pgsql/data/recovery.conf

cp /usr/pgsql-9.4/share/recovery.conf.sample /opt/pgsql/data/recovery.conf

修改recovery.conf

standby_mode = on    # 说明该节点是从服务器
primary_conninfo = 'host=192.168.20.93 port=5432 user=replica password=replica'  # 主服务器的信息以及连接的用户
recovery_target_timeline = 'latest'

3.配置postgresql.conf

wal_level = hot_standby
max_connections = 1000 # 一般查多于写的应用从库的最大连接数要比较大
hot_standby = on # 说明这台机器不仅仅是用于数据归档,也用于数据查询
max_standby_streaming_delay = 30s # 数据流备份的最大延迟时间
wal_receiver_status_interval = 10s # 多久向主报告一次从的状态,当然从每次数据复制都会向主报告状态,这里只是设置最长的间隔时间
hot_standby_feedback = on # 如果有错误的数据复制,是否向主进行反馈

配置完后重启从服务器

pg_ctl stop -D /opt/pgsql/data
pg_ctl start -D /opt/pgsql/data

5.3 验证是否部署成功

在主节点上执行:

select client_addr,sync_state from pg_stat_replication;

结果如下:

postgres=# select client_addr,sync_state from pg_stat_replication;
  client_addr  | sync_state
---------------+------------
 192.168.20.94 | async
(1 行记录)

说明94是从服务器,在接收流,而且是异步流复制。

此外,还可以分别在主、从节点上运行 ps aux | grep postgres 来查看进程:

主服务器(93)上:

postgres 262270  0.0  0.0 337844  2832 ?        Ss   10:14   0:00 postgres: wal sender process replica 192.168.20.94(13059) streaming 0/A002A88

可以看到有一个 wal sender 进程。

从服务器(94)上:

postgres 569868  0.0  0.0 384604  2960 ?        Ss   10:14   0:02 postgres: wal receiver process   streaming 0/A002B60

可以看到有一个 wal receiver 进程。

至此,PostgreSQL主从流复制安装部署完成。

在主服务器上插入数据或删除数据,在从服务器上能看到相应的变化。从服务器上只能查询,不能插入或删除。

6. 主要配置

1. 连接相关

listen_addresses = '*'      数据库用来监听客户端连接的IP地址,*表示监听所有IP。
port = 5432     数据库监听户端连接的TCP端口。默认值是5432。
max_connections = 100   允许客户端的最大连接数,默认是100,足够了。
superuser_reserved_connections = 3 为超级用户保留的连接数,默认为3。


2. 资源使用

shared_buffers = 128MB  可以被PostgreSQL用于缓存数据的内存大小。大的shared_buffers需要大的checkpoint_segments,同时需要申请更多的System V共享内存资源.这个值不需要设的太大, 因为PostgreSQL还依赖操作系统的cache来提高读性能。另外, 写操作频繁的数据库这个设太大反而会增加checkpoint压力(除非你使用了SSD或者IOPS能力很好的存储).
work_mem = 4MB   内部排序和哈希操作可使用的工作内存大小。
maintenance_work_mem = 64MB 这里定义的内存只是在CREATE INDEX, VACUUM等时用到。这个值越大, VACUUM, CREATE INDEX的操作越快, 当然大到一定程度瓶颈就不在内存了, 可能是CPU例如创建索引.这个值是一个操作的内存使用上限, 而不是一次性分配出去的. 并且需要注意如果开启了autovacuum, 最大可能有autovacuum_max_workers*maintenance_work_mem的内存被系统消耗掉.


3. WAL

wal_level = hot_standby  如果需要做数据库WAL日志备份的话至少需要设置成archive级别, 如果需要做hot_standby那么需要设置成hot_standby。hot_standby意味着WAL记录得更详细, 如果没有打算做hot_standby设置得越低性能越好。
fsync = on  强制把数据同步更新到磁盘
wal_buffers = -1  默认是-1 根据shared_buffers的设置自动调整shared_buffers*3% .最大限制是XLOG的segment_size.
checkpoint_segments = 3  多少个xlog file产生后开始checkpoint操作。建议设置为shared_buffers除以单个XLOG文件的大小。
checkpoint_timeout = 5min 这个和checkpoint_segments的效果是一样的, 只是触发的条件是时间条件。
archive_mode = on 允许归档。
archive_command = 'cp %p /opt/pgsql/pg_archive/%f'  归档调用的命令。


4. 主从复制

## postgresql.conf

max_wal_senders = 32 最大的wal sender进程数。
hot_standby = on  在从服务器上设置为 on ,则该服务器也可用作查询。
max_standby_streaming_delay = 30s  数据流备份的最大延迟时间。
wal_receiver_status_interval = 10s  多久向主报告一次从的状态,当然从每次数据复制都会向主报告状态,这里只是设置最长的间隔时间。
hot_standby_feedback = on  如果有错误的数据复制,是否向主进行反馈。

## recovery.conf(只有从服务器需要配置)

standby_mode = on  说明该节点是从服务器
primary_conninfo = 'host=192.168.20.93 port=5432 user=replica password=replica'  主服务器的信息以及连接的用户
recovery_target_timeline = 'latest'


5. 内核资源

max_files_per_process = 1000 设定每个数据库进程能够打开的文件的数目。默认值是1000。
shared_preload_libraries = ''  设置数据库在启动时要加载的操作系统共享库文件。如果有多个库文件,名字用逗号分开。如果数据库在启动时未找到shared_preload_libraries指定的某个库文件,数据库将无法启动。默认值为空串。

6. AUTOVACUUM参数

autovacuum = on  是否打开数据库的自动垃圾收集功能。默认值是on。如果autovacuum被设为on,参数track_counts也要被设为on,自动垃圾收集才能正常工作。注意,即使这个参数被设为off,如果事务ID回绕即将发生,数据库会自动启动一个垃圾收集操作。这个参数只能在文件postgresql.conf中被设置。
log_autovacuum_min_duration = -1  单位是毫秒。如果它的值为0,所有的垃圾搜集操作都会被记录在数据库运行日志中,如果它的值是-1,所有的垃圾收集操作都不会被记录在数据库运行日志中。如果把它的值设为250毫秒,只要自动垃圾搜集发出的VACUUM和ANALYZE命令的执行时间超过250毫秒,VACUUM和ANALYZE命令的相关信息就会被记录在数据库运行日志中。默认值是-1。
autovacuum_max_workers = 3  设置能同时运行的最大的自动垃圾收集工作进程的数目。默认值是3。
autovacuum_naptime = 1min  设置自动垃圾收集控制进程的睡眠时间。
autovacuum_vacuum_threshold = 50  设置触发垃圾收集操作的阈值。默认值是50。只有一个表上被删除或更新的记录的数目超过了autovacuum_vacuum_threshold的值,才会对这个表执行垃圾收集操作。

7. 文件位置

data_directory = '/opt/pgsql/data'           数据存放位置,初始化时可以指定,也可以在这里修改。
hba_file = '/opt/pgsql/data/pg_hba.conf'     主从复制配置文件pg_hba.conf的路径
ident_file = /opt/pgsql/data/pg_ident.conf'   配置文件pg_ident.conf的路径

8. 编码

lc_messages = 'zh_CN.UTF-8'                系统错误信息的语言环境
lc_monetary = 'zh_CN.UTF-8'                货币格式的语言环境
lc_numeric = 'zh_CN.UTF-8'                 数字的语言环境
lc_time = 'zh_CN.UTF-8'                    时间的语言环境

7. 插件(扩展)

PostgreSQL的contrib/目录和extension/目录附带包含若干插件的源代码。 在附录 F中被描述。其它插件是独立开发的, 比如PostGIS。 甚至PostgreSQL的复制方案也是在外部开发的。 比如 Slony-I 是一个流行的主/从复制方案,它就是独立在核心项目之外开发的。

PostgreSQL的插件主要用来提供新的用户自定义函数,操作符,或类型。 若要使用插件,需要在数据库系统中注册新的SQL对象。(如果该插件没有在contrib或extension目录下,需要先自己安装,或者在编译源码的时候指定。) 在PostgreSQL 9.1和以后版本,这是通过执行 CREATE EXTENSION命令来实现。

CREATE EXTENSION module_name 

此命令必须由数据库管理员运行。如想在某个数据库中使用该插件,则必须在该数据库中运行如上命令。另外, 在数据库template1中运行它,这样在随后创建的数据库中也可使用该插件。

具体插件的安装使用请参考下一节:PostGIS插件安装与使用

8. PostGIS插件安装与使用

8.1 简介

PostGIS是对象关系型数据库PostgreSQL的一个插件,PostGIS提供如下空间信息服务功能:空间对象、空间索引、空间操作函数和空间操作符。同时,PostGIS遵循OpenGIS的规范。

PostGIS支持所有的空间数据类型,这些类型包括:点(POINT)、线(LINESTRING)、多边形(POLYGON)、多点 (MULTIPOINT)、多线(MULTILINESTRING)、多多边形(MULTIPOLYGON)和集合对象集 (GEOMETRYCOLLECTION)等。PostGIS支持所有的对象表达方法,比如WKT和WKB。

PostGIS支持所有的数据存取和构造方法,如GeomFromText()、AsBinary(),以及GeometryN()等。

PostGIS提供简单的空间分析函数(如Area和Length)同时也提供其他一些具有复杂分析功能的函数,比如Distance。

PostGIS提供了对于元数据的支持,如GEOMETRY_COLUMNS和SPATIAL_REF_SYS,同时,PostGIS也提供了相应的支持函数,如AddGeometryColumn和DropGeometryColumn。

PostGIS提供了一系列的二元谓词(如Contains、Within、Overlaps和Touches)用于检测空间对象之间的空间关系,同时返回布尔值来表征对象之间符合这个关系。

PostGIS提供了空间操作符(如Union和Difference)用于空间数据操作。比如,Union操作符融合多边形之间的边界。两个交迭的多边形通过Union运算就会形成一个新的多边形,这个新的多边形的边界为两个多边形中最大边界。

PostGIS还提供以下功能:

数据库坐标变换

数据库中的几何类型可以通过Transform函数从一种投影系变换到另一种投影系中。在OpenGIS中的几何类型都将SRID作为自身结构的一部分,但不知什么原因,在OpenGIS的SFSQL规范中,并没有引入Transform。

球体长度运算

存储在普通地理坐标系中的集合类型如果不进行坐标变换是无法进行程度运算的,OpenGIS所提供的坐标变换使得积累类型的程度计算变成可能。

三维的几何类型

SFSQL规范只是针对二维集合类型。OpenGIS提供了对三维集合类型的支持,具体是利用输入的集合类型维数来决定输出的表现方式。例如,即便 所有几何对象内部都以三维形式存储,纯粹的二维交叉点通常还是以二维的形式返回。此外,还提供几何对象在不同维度间转换的功能。

空间聚集函数

在数据库中,聚集函数是一个执行某一属性列所有数据操作的函数。比如Sum和Average,Sum是求某一关系属性列的数据总和,Average 则是求取某一关系属性列的数据平均值。与此对应,空间聚集函数也是执行相同的操作,不过操作的对象是空间数据。例如聚集函数Extent返回一系列要素中 的最大的包裹矩形框,如“SELECT EXTENT(GEOM) FROM ROADS”这条SQL语句的执行结果是返回ROADS这个数据表中所有的包裹矩形框。

栅格数据类型

PostGIS通过一种新的数据类型片,提供对于大的栅格数据对象的存储。片由以下几个部分组成:包裹矩形框、SRID、类型和一个字节序列。通过 将片的大小控制在数据库页值(32×32)以下,使得快速的随即访问变成可能。一般大的图片也是通过将其切成32×32像素的片然后再存储在数据库中的。

8.2 部署

8.2.1 安装PostGIS

yum install postgis2_94   # 因为安装的PostgreSQL版本为9.4,所以是postgis2_94

注:
需要PostgreSQL9.1以上版本才支持PostGIS.

8.2.2 使PostGIS可用

想要在PostgreSQL中使用PostGIS插件,安装只是第一步。每个数据库想要使用PostGIS必须先在该数据库中使PostGIS可用。假设我们想在gisdb这个数据库中使用PostGIS,先进入gisdb数据库,执行以下步骤:

gisdb=# CREATE EXTENSION postgis;
gisdb=# CREATE EXTENSION postgis_topology;

8.2.3 查看是否安装成功

在gisdb数据库中输入\du,查看已安装的插件

gisdb=# \dx
                                             已安装扩展列表
     名称       | 版本  |  架构模式  |                                描述
------------------+-------+------------+---------------------------------------------------------------------
plpgsql          | 1.0   | pg_catalog | PL/pgSQL procedural language
postgis          | 2.1.8 | public     | PostGIS geometry, geography, and raster spatial types and functions
postgis_topology | 2.1.8 | topology   | PostGIS topology spatial types and functions
(3 行记录)

可以看到已经安装了postgis和postgis_topology。

8.3 使用

8.3.1 创建空间数据表

首先建立一个常规的表格存储有关城市(cities)的信息。这个表格有两栏,一个是 ID 编号,一个是城市名:

gisdb=# CREATE TABLE cities (id int4, name varchar(50));

现在添加一个空间列用于存储城市的位置。习惯上这个列叫做 the_geom。它记录了数据为什么类型(点、线、面)、有几维(这里是二维)以及空间坐标系统。此处使用 EPSG:4326 坐标系统:

gisdb=# SELECT AddGeometryColumn ('cities', 'the_geom', 4326, 'POINT', 2);

完成后,查询 cities 表单应当显示这个新栏目。同时页面将显示当前表达没有记录(0 rows)。

gisdb=# select * from cities;
 id |      name       |                      the_geom
----+-----------------+----------------------------------------------------
(0行记录)

为添加记录,需要使用 SQL 命令。对于空间列,使用 PostGIS 的 ST_GeomFromText可以将文本转化为坐标与参考系号的记录:

gisdb=# INSERT INTO cities (id, the_geom, name) VALUES (1,ST_GeomFromText('POINT(-0.1257 51.508)',4326),'London, England');
gisdb=# INSERT INTO cities (id, the_geom, name) VALUES (2,ST_GeomFromText('POINT(-81.233 42.983)',4326),'London, Ontario');
gisdb=# INSERT INTO cities (id, the_geom, name) VALUES (3,ST_GeomFromText('POINT(27.91162491 -33.01529)',4326),'East London,SA');

当然,这样的输入方式难以操作。其它方式可以更快的输入数据。就目前来说,表格内已经有了一些城市数据,可以先进行查询等操作。

8.3.2 简单查询

标准的 SQL 操作都可以用于 PostGIS 表:

gisdb=# SELECT * FROM cities;
 id |      name       |                      the_geom
----+-----------------+----------------------------------------------------
  1 | London, England | 0101000020E6100000BBB88D06F016C0BF1B2FDD2406C14940
  2 | London, Ontario | 0101000020E6100000F4FDD478E94E54C0E7FBA9F1D27D4540
  3 | East London,SA  | 0101000020E610000040AB064060E93B4059FAD005F58140C0
(3 行记录)

这里的坐标是无法阅读的 16 进制格式。要以 WKT 文本显示,使用 ST_AsText(the_geom) 或ST_AsEwkt(the_geom) 函数。也可以使用 ST_X(the_geom) 和 ST_Y(the_geom) 显示一个维度的坐标:

gisdb=#  SELECT id, ST_AsText(the_geom), ST_AsEwkt(the_geom), ST_X(the_geom), ST_Y(the_geom) FROM cities;
 id |          st_astext           |               st_asewkt                |    st_x     |   st_y
----+------------------------------+----------------------------------------+-------------+-----------
  1 | POINT(-0.1257 51.508)        | SRID=4326;POINT(-0.1257 51.508)        |     -0.1257 |    51.508
  2 | POINT(-81.233 42.983)        | SRID=4326;POINT(-81.233 42.983)        |     -81.233 |    42.983
  3 | POINT(27.91162491 -33.01529) | SRID=4326;POINT(27.91162491 -33.01529) | 27.91162491 | -33.01529
(3 行记录)

8.3.3 空间查询

PostGIS 为 PostgreSQL 扩展了许多空间操作功能。以上已经涉及了转换空间坐标格式的 ST_GeomFromText 。多数空间操作以 ST(spatial type)开头,在 PostGIS 文档相应章节有罗列。这里回答一个具体的问题:上面三个城市相互的距离是多少?查询语句怎么写?

gisdb=# SELECT p1.name,p2.name,ST_Distance_Sphere(p1.the_geom,p2.the_geom) FROM cities AS p1, cities AS p2 WHERE p1.id > p2.id;
      name       |      name       | st_distance_sphere
-----------------+-----------------+--------------------
 London, Ontario | London, England |   5875787.03777356
 East London,SA  | London, England |   9789680.59961472
 East London,SA  | London, Ontario |   13892208.6782928
(3 行记录)

输出显示了距离数据。注意 ‘WHERE’ 部分防止了输出城市到自身的距离(0)或者两个城市不同排列的距离数据(London, England 到 London, Ontario 和 London, Ontario 到 London, England 的距离是一样的)。

9. 参考资料

《PostgreSQL初探》 FullStackPlan

欢迎关注公众号: FullStackPlan 获取更多干货哦~

    原文作者:Jeffbond
    原文地址: https://www.jianshu.com/p/1f15ba3c7023
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞