重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
说起数据库,大家耳熟能详的商业数据库产品当推Oracle、微软的SqlServer和IBM的
成都创新互联坚持“要么做到,要么别承诺”的工作理念,服务领域包括:成都网站设计、做网站、企业官网、英文网站、手机端网站、网站推广等服务,满足客户于互联网时代的双清网站设计、移动媒体设计的需求,帮助企业找到有效的互联网解决方案。努力成为您成熟可靠的网络建设合作伙伴!
DB2等,而开源数据库中则有两大产品MySQL和PostgreSQL。
PostgreSQL 是一种对象-关系型数据库管理系统(ORDBMS),也是目前功能最强大、
特性最丰富和最复杂的自由软件数据库系统。它起源于伯克利(BSD)的数据库研究计划,
目前是最重要的开源数据库产品开发项目之一,有着非常广泛的用户。
PostgreSQL 可以说是最富特色的自由数据库管理系统,也有人认为可以是最强大的自由
软件数据库管理系统。PostgreSQL 是唯一支持事务、子查询、多版本并行控制系统、数据完
整性检查等特性的唯一的一种自由软件的数据库管理系统。能在多平台下---包括Linux、
FreeBSD和Windows等---运行,并且支持多语言的开发。
在两大开源数据库产品的对比中,一般认为MySQL速度更快,所以得到更为广泛的使
用;而PostgreSQL性能更为先进,PostgreSQL 提供很多 MySQL 目前所不支持的特性,比
如触发器、视图、存储过程等等,在记录数超千万之后性能表现尤其出色。
当前的最新版本是PostgreSQL 8.2.3,官方网站是:
1.2 什么是PostGIS
PostGIS在对象关系型数据库PostgreSQL上增加了存储管理空间数据的能力,相当于
Oracle的spatial部分。PostGIS最大的特点是符合并且实现了OpenGIS的一些规范,是最著
名的开源GIS数据库。
当前的最新版本是PostGIS 1.2.1,官方网站是:
二 PostgreSQL和PostGIS的安装
2.1 在windows下安装。
新版本的PostgreSQL在其安装程序中集成了PostGIS,只需要在安装过程中选中
PostGIS和pgsql项就可以了。
2.2 在Debian下安装PostGIS
# apt-get install postgresql-8.1 postgresql-8.1-postgis
当前Etch中的版本:PostgreSQL是8.1.7,而PostGIS是1.1.6,虽然不是最新的版本,
但已经足够了。
还需要做的工作是:
1) 创建一个专门用于PostGIS的数据库并为专用数据库导入PostGIS支持:
# su – postgres
$ cd /usr/share/postgresql-8.1-postgis
$ createdb wen1
$ createlang plpgsql wen1
$ psql -d wen1 -f lwpostgis.sql
$ psql -d wen1 -f spatial_ref_sys.sql
2) 创建一个专门的用户,并把相应的数据库和数据表的属主设置为该用户:
# su – postgres
$ psql
$ create user wen1 password ‘123456’;
$ alter database wen1 owner to wen1;
$ alter table spatial_ref_sys owner to wen1;
$ alter table geometry_columns owner to wen1 ;
3) 修改PostgreSQL配置文件以便可以远程使用。
修改PostgreSQL的配置文件/etc/postgresql/8.1/main/Postgresql.conf,将其中的一句:
listen_address=’localhost’
前面的注释去掉,并把’localhost’该为’*’。
修改Postgresql的配置文件/etc/postgresql/8.1/main/pg_hba.conf,在文件后面加一句:
host all all 192.168.0.0/24 password
这句的意思是:同网络中192.168.0.*的机器可以以密码的形式使用所有的数据库。更具
体的参数意义直接看该配置文件中的注释就可以了。
这里一定要配置正确,否则无法在远程连接PostgreSQL数据库。
2.3 源码安装PostgreSQL和PostGIS
参阅以前写的老文章。
三 PostGIS的使用
要使用PostGIS,需要两方面的预备知识,一是要熟悉基本的SQL语法;二是熟悉
PostgreSQL数据库的基本使用。
(一) 快速入门
我们使用前面创建的数据库wen2,用户为wen1,现在创建一个包含三个点的数据库
test1:
首先在Etch下以wen1登陆,然后打开wen2数据库:
$ psql -d wen2 ;
再在PostgreSQL的控制台下输入以下命令:
wen2= create table test1 (myID int4, pt geometry, myName
varchar );
wen2= insert into test1 values (1, 'POINT(0 0)', 'beijing'
);
wen2= insert into test1 values (2, 'POINT(31.5 60.87)',
'shanghai' );
wen2= insert into test1 values (3, 'POINT(10.77 85.902)',
'tianjin' );
这样我们利用PostGIS创建了一个包含三个点的GIS数据表。
为了能在QGIS中打开这一图层,我们还需要为数据表创建一个主键:
wen2=alter table test1 add primary key (myID);
可以看到PostGIS的使用其实就相当于使用一个经过扩展的SQL语法,上述语句熟悉
SQL语法的人一看都很熟悉,都是普通的SQL语句,不同的只不过是增加了PostGIS特殊的
geometry数据类型。
你可以再试试这些SQL语句:
select * from test1;
select myID,AsText(pt) from test1;
select Distance(pt, 'POINT(0 0)') from test1;
(二) PostGIS的Geometry数据类型
Geometry可以说是PostGIS最重要的一个概念,是“几何体”的意思,由于PostGIS很
好地遵守OGC的”Simple Feature for Specification for
SQL”规范,目前支持的几何体类型包
含其实例有:
POINT(1 1)
MULTIPOINT(1 1, 3 4, -1 3)
LINESTRING(1 1, 2 2, 3 4)
POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))
MULTIPOLYGON((0 0, 0 1, 1 1, 1 0, 0 0), (5 5, 5 6, 6 6, 6 5, 5
5))
MULTILINESTRING((1 1, 2 2, 3 4),(2 2, 3 3, 4 5))
而geometry具体表现又有两种形式,一种叫做WKT(Well Known Text)形式,如上面的
例子。或者使用如下SQL语句浏览:
select AsText(pt) from test1;
另一种叫做“Canonical Form”形式,看上去是一串古怪的数字,其实是一种增强的十六
进制编码,使用如下SQL语句就可以浏览了:
select pt from test1;
(三) 读写PostGIS数据
建设好PostGIS数据库之后,我们现在需要进行读写GIS数据了,包括把GIS写入到
PostGIS数据库中以及在应用程序中使用PostGIS数据库的数据。读写PostGIS目前主要有以
下四种方式:
3.1 使用psql语言
Psql语言是PostgreSQL内嵌的一个命令行工具,其语法基本上和标准的SQL语法是一
致的,可以使用Psql工具,结合标准SQL语法和一些PostGIS的扩展对PostGIS数据库进行
读写操作。
具体例子如上面“快速入门”中的例子。
这种方式功能强大,但全部需要手工操作,烦琐且繁重。
3.2 使用一些小工具
有两个很有用的小的转换工具,一是shp2pg;一是ogr2ogr
3.2.1 shp2pgsql和pgsql2shp
shp2pgsql和pgsql2shp是PostGIS自身携带的一对在Shape文件和PostGIS数据库之间进
行转换的工具,在Debian中安装好PostGIS之后,这两个程序已经位于可执行文件的搜索路
径上,因此可以在系统中任何位置使用。
假如当前目录下有完整的china.shp文件(应该有三个同名不同扩展名的文件),需要把其
中数据输入到上述的wen2数据库中的数据表china_postgis中,具体操作为(操作用户为
wen1):
$ shp2pgsql china china_postgis tmp.sql
$ psql -d wen2 -f roads.sql
这个工具很好用,缺点在于使用范围有限,只针对Shape文件格式。
3.2.2 ogr2ogr
PostGIS本身的shp2pg工具只把shape文件转换到PostGIS 数据库中,那如何把其他的
GIS数据加入呢?比如说MapInfo的mid格式,ESRI的e00格式呢?这就要使用ogr这个工
具了。
Ogr目前是gdal的一个组成部分,那什么是gdal呢?其官方主页()上
如此介绍:
GDAL is a translator library for raster geospatial data formats
that is released under an X/MIT
style Open Source license by the Open Source Geospatial
Foundation. As a library, it presents a
single abstract data model to the calling application for all
supported formats. It also comes with a
variety of useful commandline utilties for data translation and
processing.
简单地说,Gdal是一个各种Gis数据格式的转换软件库,ogr则是转换矢量GIS数据的
软件库。
目前ogr能够支持的数据格式包括:
Arc/Info Binary Coverage、DWG、ESRI Personal
GeoDatabase、ArcSDE、ESRI
Shapefile、GML、GRASS、Mapinfo File、Microstation DGN、ODBC、Oracle
Spatial和
PostgreSQL等。应该说,这就基本包括了我们平常用到的所有矢量型GIS文件格式了。
Gdal支持的栅格数据格式参阅http: //
下面我们从源码编译安装gdal---因为我在Debian下使用apt方式安装的gdal并不支持
postgresql数据库,其实更为简便的方法也许是去gdal.org下载一个Fwtools的工具包,可以
直接运行不用繁琐的编译,既有Windows的,也有Linux下用的,只不过这个包有些大。
1) 下载最新的gdal-1.3.2
2) 解压
3) ./configure --prefix=/opt/gdal
--with-pg=/opt/pg/bin/pg_config --without-ogdi
这里我习惯把软件安装在/opt目录下。
--with-pg参数很重要,使ogr可以支持PostGIS,后面的参数是我的PostGIS安装的地方。
我在这里编译很多次失败,经过仔细查找,发现问题出在ogdi上,所以暂时我只好使
它不支持ogdi。
4) make
5) make install
下面是使用过程,假设现在我要把一个rai.mid文件导入到数据库data1中:
$ ogr2ogr –f Postgresql PG:dbname=data1 rai.mid
注意,f参数后面跟的是导入的数据类型,最后那个文件才是要导出的文件。PG后面说
明的是数据库的名字,需要是已经创建好的数据库,而数据表则由程序自动创建。还要特别
注意权限问题,以上命令我是由postgres用户执行的。
还有一个要注意的是主键问题。一般情况下,你使用shp2pg或者 ogr2ogr向postgis中
增加了Gis数据后,在GIS客户端添加postgis图层的时候,常常会因为数据表没有定义主键
而出错,解决的办法是,在服务器上使用psql或者其他sql工具,使用命令:
alter table table_name add primary key (column_name);
另外我们发现ogr竟然是不支持最常见的GIS格式e00格式,好象是因为版权方面的原
因吧。解决的方法就是去sf.net查找相关工具。我在上面就找到一个e002pg工具,支持将
e00文件导入到postGIS数据库中。
3.3 在其他GIS软件中读写PostGIS数据
比如在QGIS中,能够打开PostGIS图层,还有SPIT插件可以把Shape文件输入到
PostGIS数据库中。
其他GIS软件如uDig,Grass等,甚至连ArcInfo都支持或部分支持读写PostGIS数据。
3.4 利用接口在应用程序中读写PostGIS数据
广大的开源GIS程序员几乎为每一种程序设计语言设计好了读写PostGIS的接口,如利
用PostgreSQL的JDBC库,可以使用Java语言在程序中读写PostGIS数据;利用libpq库,
可以使用C语言读写PostGIS数据。
(四) 使用PostGIS函数
4.1 PostGIS函数
要能熟练使用PostGIS,掌握PostGIS的所有函数是关键。通过掌握这些PostGIS函数,
我们能够高效、稳定地处理各种地理数据。由于PostGIS的函数设计时都遵守OpenGIS规范,
我们也可以把这些PostGIS叫做OpenGIS函数。
4.2 PostGIS函数的分类
PostGIS函数大致可以分为以下四类
1) 字段处理函数
这类函数当前一共有3个,分别是:
AddGeometryColumn(var1,var2,var3,var4,var5,var6):为已有的数据表增加一个地理几何
数据字段。Var1代表数据表的模式(schema)的名字,一般是public,也可以省略,则使用当
前的缺省模式;var2是已有的数据表的名字;var3是新的地理数据字段的名字;var4是
SRID值,不确定的话就取-1吧;var5是地理数据的类型,可以是POINT等;var6是指该几
何数据是二维还是三维数据。
前面的SQL语句 create table test1 (myID int4, pt geometry, myName
varchar )更规范的写
法为:
create table test1 (myID int4, myName varchar );
select AddGeometryColumn('test1','pt',-1,'GEOMETRY',2);
DropGeometryColumn函数显然是删除一个地理数据字段的;
SetSRID函数显然是设置SRID值的。
2) 几何关系函数
这类函数目前共有10个,分别是:
Distance Equals Disjoint Intersects Touches Crosses Within
Overlaps Contains Relate
3) 几何分析函数
这类函数目前共有12个,分别是:Centroid Area Lenth PointOnSurface Boundary
Buffer
ConvexHull Intersection SymDifference Difference GeomUnion
MemGeomUnion
4) 读写函数
这类函数很多,主要是用于在各种数据类型之间的转换,尤其是在于Geometry数据类
型与其他如字符型等数据类型之间的转换,函数名如AsText、GeomFromText等,其作用是
显然的。
4.3 PostGIS函数使用示例。
假设在我们的wen2数据库中,有两张表,一张为guojia,是从“国家基础地理数据”
网站下载的国界数据表,数据类型为LINE;二为shengqu_polygon,也从同一个网站下载,
地理数据类型为多边形。
1) 查询我国边境线的长度:
wen1= select sum(length(the_geom)) as lenth from guojie;
2) 查询我国面积最大的省区名字:
wen1= select name area(the_geom) as myarea
from shengqu_polygon
order by myarea DESC
LIMIT 1;
(五) 使用PostGIS扩展函数
除了上述遵循OpenGIS的函数之外,PostGIS还自行扩展了一些当前OpenGIS规范之外
的函数,主要包括以下几类:
5.1 管理类函数
扩展的管理类函数主要包括一些软件版本查询函数,如
postgis_version()、postgis_geos_version()、postgis_proj_version()函数等,分别查询当前的
PostGIS的版本及其使用的Geos和Proj库的版本。
5.2 数据类型的输入输出函数
除了OpenGIS定义的地理数据类型之外,PostGIS还对数据类型进行了扩展,这种扩展
主要是两方面的扩展,一是把二维的数据向三维和四维扩展;二就是在WKT和WKB数据
类型基础上扩展出EWKT和EWKB数据类型。
PostGIS提供了在这些地理数据类型和常用数据类型如字符型、浮点型数据之间进行转
换的函数。
5.3 量算函数
如length3d函数是对length2d函数的扩展。
5.4 几何操作函数
如addBBox(geometry)函数给所给的几何体加上一个边框。
如simplify(geometry,tolerance)函数可以对折线和多边形利用Douglas-Peuker算法进行一
些节点进行删除,从而使表现的图形更简单而清晰,在网络传输数据时具有更高的效率。
5.5 操作符号
5.6 其他扩展函数
(六) 建立PostGIS索引
当数据库的记录增大的时候,如果没有建立索引的话,操作的效率就显著下降。
POstGIS建议当记录数超过几千的时候就应该建立索引,而GIS数据库一般都是海量数据,
所以对PostGIS而言,索引就非常重要。
Shapfile文件为ESRI公司的文件存储格式,并且得到了业界广泛的支持。Shapfile格式是一种简单的,用非拓朴关系的形式存储几何位置和地
理特征的属性信息的格式。虽然GeoServer采用Shapfile文件可以快速的创建网上地图服务,但它的缺点确很明显:
1、Shapefile只支持一个图层,在实际中没有意义。
2、直接保用SHP文件不安全,Shapfile文件很容易被病毒或其他原因误删除。
3、GeoServer中用Shapfile文件作数据源的效率是很低的。
4、Shapfile中的汉字GeoServer不能解析,会出现乱码。
5、数据库可以方便的对地理信息进行查询。
用PostGIS管理空间数据
PostGIS支持GIST空间索引(附录1)、规范窗体,能很大的提高处理效率。
OGC格式只提供二维的几何体,且相关联的SRID从未深入的用于输入输出请求,PostGIS支持OpenGIS组织"Simple
Features for
SQL"规范指定的所有GIS对象和函数,并进行了扩展,格式是EWKB、EWKT,其中增加了对3DZ,3DM和4D
坐标系的支持(当然三维、四维数据的OGC标准还未完全制定),深入引进了SRID信息。
空间数据表结构:PostGIS中存在两个必需的元数据表格, SPATIAL_REF_SYS(空间参考表格) 和
GEOMETRY_COLUMNS(几何体属性列),两个表用于存储空间数据库使用的坐标系统数字ID和文本描述。
PostGIS的shp2pgsql命令可以将Shapfile直接导入到数据库中也可以导出为SQL文件,推荐先导出为SQL文件再将此文件在SQL运行窗口中执行可将数据导入数据库。
Shapfile到SQL语句:
shp2pgsql 路径shp数据文件名 新建的数据表名
路径SQL文件名.sql
Shapfile直接入库:
shp2pgsql -c 路径shp数据文件名 新建的数据表名 数据库名|psql -d 数据库名
举例说明:
如将一Shapfile文件“c:road.shp”导入到数据表“road”中,数据库为“sjzmap”。
1、运行“命令提示符”。
2、切换至PostgreSQL数据库安装目录中的bin目录下。
3、执行此目录下的shp2pgsql命令:“shp2pgsql c:road.shp road
c:road.sql”。
4、如将此文件直接导入数据库(不推荐):“shp2pgsql -c c:road.shp road
sjzmap | psql -d sjzmap”。
5、使用pgAdmin3
选择数据库,再导入表。
1、windows下postgresql的安装
我下载的为xxx9.2.exe一路默认安装即可。安装位置为C:\Program Files\PostgreSQL。
安装完毕后,在dos下执行命令
net user
列出当前系统用户名称。我的用户名为Administrator。
psql –U Administrator –d postgres
该命令表示通过数据库用户Administrator连接数据库postgres。
l 若显示psql不是内部或外部命令,则说明postgresql的bin文件路径没添加到windows系统中,右击“我的电脑”-”属性”-”高级”-”环境变量”-”Administrator”的用户变量,选中“PATH”,点击编辑,将”C:\Program Files\PostgreSQL\9.2\bin”添加进去,注意与前面的路径用”;”隔开。电脑重启生效。
l 若显示角色Administrator不存在,则必须在postgresql数据库中添加该用户才能使其可以登录。
在postgresql中
查询系统用户
postgres=#select* from pg_user;
查询系统中的数据库
postgres=#select* from pg_database;
说明一下:“template1”是Postgresql在初始化时自动创建的测试数据库。
创建postgresql数据库Administrator用户
方式1
在PostgreSQL中创建用户postgreSQL用户Administrator
用SQL Shell(psql)通过用户postgres登录PostgreSQL,创建用户Administrator,
postgres=#create user “Administrator”;
方式2
通过windows下dos创建postgresql用户Administrator
将PostgreSQL文件夹bin路径添加到系统环境中后重启生效.
通过windows下dos创建postgresql用户是区分大小写的。
配置客户机访问
为了配置远程主机和用户可以连接到PostgreSQL服务,你需要pg_hba.conf文件。文件包含大量注释记录用于远程访问的选项。在我们的安装示例中,我们允许局域网中任何主机的任何用户访问服务器上的数据库。为了达到这个目的,我们添加以下的一行记录到文件尾:
host all all 192.168.0.0/16 trust
这意味着所有IP地址由192.168开始的计算机可以访问所有的数据库。最简单的使配置生效的方法就是重启服务器。
在dos下操作,通过createuser –Uolduser –P newuser来创建。
比如我们想创建postgresql数据库用户Administrator。
createuser –U postgre –P Administrator
这样创建的数据库用户Administrator没有创建数据库的权利,可以通过pgAdmin III登录进行查看。
若使其可以创建数据库可以参照下面内容进行设置:
createuser –U postgre –s Administrator
这样具有创建数据库能力。
createuser的用法可以通过在dos中输入createuser –help查看。
MicrosoftWindows XP [版本 5.1.2600]
(C)版权所有 1985-2001 Microsoft Corp.
C:\Documentsand Settings\Administratorcreateuser --help
createuser创建一个新的 PostgreSQL 用户.
使用方法:
createuser [选项]... [用户名]
选项:
-c, --connection-limit=N 角色的连接限制(缺省: 没有限制)
-d, --createdb 此角色可以创建新数据库
-D, --no-createdb 此角色不可以创建新数据库(默认)
-e, --echo 显示发送到服务端的命令
-E, --encrypted 口令加密存储
-i, --inherit 角色能够继承它所属角色的权限
(这是缺省情况)
-I, --no-inherit 角色不继承权限
-l, --login 角色能够登录(这是缺省情况)
-L, --no-login 角色不能登录
-N, --unencrypted 口令不加密存储
-P, --pwprompt 给新角色指定口令
-r, --createrole 这个角色可以创建新的角色
-R, --no-createrole 这个角色没有创建其它角色的权限(默认)
-s, --superuser 角色将是超级用户
-S, --no-superuser 角色不能是超级用户(默认)
-V, --version 输出版本信息, 然后退出
--interactive 提示缺少角色名及其属性
而不是使用默认值
--replication 角色能启动复制
--no-replication 角色不能启动复制
-?, --help 显示此帮助, 然后退出
联接选项:
-h, --host=HOSTNAM 数据库服务器所在机器的主机名或套接字目录
-p, --port=PORT 数据库服务器端口号
-U, --username=USERNAME 联接用户 (不是要创建的用户名)
-w, -no-password 永远不提示输入口令
-W, --password 强制提示输入口令
臭虫报告至pgsql-bugs@postgresql.org.
C:\Documentsand Settings\Administrator
方式3
在C:\Program Files\PostgreSQL\9.2\bin文件夹下有可执行文件createuser.exe,我双击后,该文件执行一闪就关闭,只好在dos中输入cmd打开窗口,将该文件拖入窗口中,在输入“ –U postgres –P Adiminisrator”然后回车,如下图所示,即可创建数据库用户Administrator。但此时该用户不具有创建database的能力,可以通过pgAdmin III查看。
psql的用法可以通过在dos下输入psql –help查看,如下图所示。
MicrosoftWindows XP [版本 5.1.2600]
(C) 版权所有1985-2001 Microsoft Corp.
C:\Documentsand Settings\Administratorpsql --help
psql是PostgreSQL 的交互式客户端工具。
使用方法:
psql [选项]... [数据库名称 [用户名称]]
通用选项:
-c,--command=命令 执行单一命令(SQL或内部指令)然后结束
-d, --dbname=数据库名称 指定要连接的数据库 (缺省:"Administrator")
-f, --file=文件名 从文件中执行命令然后退出
-l, --list 列出所有可用的数据库,然后退出
-v, --set=, --variable=名称=值
为psql变量(名称)设定值
-V, --version 输出版本信息, 然后退出
-X, --no-psqlrc 不读取启动文档(~/.psqlrc)
-1 ("one"), --single-transaction
作为一个单一事务来执行命令文件
-?, --help 显示此帮助, 然后退出
输入和输出选项:
-a, --echo-all 显示所有来自于脚本的输入
-e, --echo-queries 显示发送给服务器的命令
-E, --echo-hidden 显示内部命令产生的查询
-L, --log-file=文件名 将会话日志写入文件
-n, --no-readline 禁用增强命令行编辑功能(readline)
-o, --output=FILENAME 将查询结果写入文件(或 |管道)
-q, --quiet 以沉默模式运行(不显示消息,只有查询结果)
-s, --single-step 单步模式 (确认每个查询)
-S, --single-line 单行模式 (一行就是一条 SQL 命令)
输出格式选项 :
-A, --no-align 使用非对齐表格输出模式
-F, --field-separator=字符串
设字段分隔符(缺省:"|")
-H, --html HTML 表格输出模式
-P, --pset=变量[=参数] 设置将变量打印到参数的选项(查阅 \pset 命令)
-R, --record-separator=字符串
设定记录分隔符(缺省:换行符号)
-t, --tuples-only 只打印记录i
-T, --table-attr=文本 设定 HTML 表格标记属性(例如,宽度,边界)
-x, --expanded 打开扩展表格输出
-z, --field-separator-zero
设置字段分隔符为字节0
-0, --record-separator-zero
设置记录分隔符为字节0
联接选项:
-h, --host=主机名 数据库服务器主机或socket目录(缺省:"本地接口")
-p, --port=端口 数据库服务器的端口(缺省:"5432")
-U, --username=用户名 指定数据库用户名(缺省:"Administrator")
-w, --no-password 永远不提示输入口令
-W, --password 强制口令提示 (自动)
更多信息,请在psql中输入"\?"(用于内部指令)或者"\help"(用于SQL命令),
或者参考PostgreSQL文档中的psql章节.
臭虫报告至pgsql-bugs@postgresql.org.
C:\Documentsand Settings\Administrator
如果打算为项目选择一款免费、开源的数据库,那么你可能会在MySQL与PostgreSQL之间犹豫不定。MySQL与PostgreSQL都是免费、开源、强大、且功能丰富的数据库。你主要的问题可能是:哪一个才是最好的开源数据库,MySQL还是PostgreSQL呢?该选择哪一个开源数据库呢?
在选择数据库时,你所做的是个长期的决策,因为后面如果再改变决定将是非常困难且代价高昂的。你希望一开始就选择正确。两个流行的开源数据库MySQL与PostgreSQL常常成为最后要选择的产品。对这两个开源数据库的高层次概览将会有助于你选择最适合自己需要的。
MySQL
MySQL相对来说比较年轻,首度出现在1994年。它声称自己是最流行的开源数据库。MySQL就是LAMP(用于Web开发的软件包,包括Linux、Apache及Perl/PHP/Python)中的M。构建在LAMP栈之上的大多数应用都会使用MySQL,包括那些知名的应用,如WordPress、Drupal、Zend及phpBB等。
一开始,MySQL的设计目标是成为一个快速的Web服务器后端,使用快速的索引序列访问方法(ISAM),不支持ACID。经过早期快速的发展之后,MySQL开始支持更多的存储引擎,并通过InnoDB引擎实现了ACID。MySQL还支持其他存储引擎,提供了临时表的功能(使用MEMORY存储引擎),通过MyISAM引擎实现了高速读的数据库,此外还有其他的核心存储引擎与第三方引擎。
MySQL的文档非常丰富,有很多质量不错的免费参考手册、图书与在线文档,还有来自于Oracle和第三方厂商的培训与支持。
MySQL近几年经历了所有权的变更和一些颇具戏剧性的事件。它最初是由MySQL AB开发的,然后在2008年以10亿美金的价格卖给了Sun公司,Sun公司又在2010年被Oracle收购。Oracle支持MySQL的多个版本:Standard、Enterprise、Classic、Cluster、Embedded与Community。其中有一些是免费下载的,另外一些则是收费的。其核心代码基于GPL许可,对于那些不想使用GPL许可的开发者与厂商来说还有商业许可可供使用。
现在,基于最初的MySQL代码还有更多的数据库可供选择,因为几个核心的MySQL开发者已经发布了MySQL分支。最初的MySQL创建者之一Michael "Monty" Widenius貌似后悔将MySQL卖给了Sun公司,于是又开发了他自己的MySQL分支MariaDB,它是免费的,基于GPL许可。知名的MySQL开发者Brian Aker所创建的分支Drizzle对其进行了大量的改写,特别针对多CPU、云、网络应用与高并发进行了优化。
PostgreSQL
PostgreSQL标榜自己是世界上最先进的开源数据库。PostgreSQL的一些粉丝说它能与Oracle相媲美,而且没有那么昂贵的价格和傲慢的客服。它拥有很长的历史,最初是1985年在加利福尼亚大学伯克利分校开发的,作为Ingres数据库的后继。
PostgreSQL是完全由社区驱动的开源项目,由全世界超过1000名贡献者所维护。它提供了单个完整功能的版本,而不像MySQL那样提供了多个不同的社区版、商业版与企业版。PostgreSQL基于自由的BSD/MIT许可,组织可以使用、复制、修改和重新分发代码,只需要提供一个版权声明即可。
可靠性是PostgreSQL的最高优先级。它以坚如磐石的品质和良好的工程化而闻名,支持高事务、任务关键型应用。PostgreSQL的文档非常精良,提供了大量免费的在线手册,还针对旧版本提供了归档的参考手册。PostgreSQL的社区支持是非常棒的,还有来自于独立厂商的商业支持。
数据一致性与完整性也是PostgreSQL的高优先级特性。PostgreSQL是完全支持ACID特性的,它对于数据库访问提供了强大的安全性保证,充分利用了企业安全工具,如Kerberos与OpenSSL等。你可以定义自己的检查,根据自己的业务规则确保数据质量。在众多的管理特性中,point-in-time recovery(PITR)是非常棒的特性,这是个灵活的高可用特性,提供了诸如针对失败恢复创建热备份以及快照与恢复的能力。但这并不是PostgreSQL的全部,项目还提供了几个方法来管理PostgreSQL以实现高可用、负载均衡与复制等,这样你就可以使用适合自己特定需求的功能了。
平台
MySQL与PostgreSQL都出现在一些高流量的Web站点上:
MySQL:Slashdot、Twitter、Facebook与Wikipedia
PostgreSQL:Yahoo使用了一个修改的PostgreSQL数据库来处理每天数以亿计的事件,还有Reddit和Disqus
MySQL与PostgreSQL都能运行在多个操作系统上,如Linux、Unix、Mac OS X与Windows。他们都是开源、免费的,因此测试他们时的唯一代价就是你的时间与硬件。他们都很灵活且具有可伸缩性,可用在小型系统和大型分布式系统上。MySQL在一个领域上要比PostgreSQL更进一步,那就是它的触角延伸到了嵌入式领域,这是通过libmysqld实现的。PostgreSQL不支持嵌入式应用,依然坚守在传统的客户端/服务器架构上。
MySQL通常被认为是针对网站与应用的快速数据库后端,能够进行快速的读取和大量的查询操作,不过在复杂特性与数据完整性检查方面不太尽如人意。PostgreSQL是针对事务型企业应用的严肃、功能完善的数据库,支持强ACID特性和很多数据完整性检查。他们二者都在某些任务上具有很快的速度,MySQL不同存储引擎的行为有较大差别。MyISAM引擎是最快的,因为它只执行很少的数据完整性检查,适合于后端读操作较多的站点,不过对于包含敏感数据的读/写数据库来说就是个灾难了,因为MyISAM表最终可能会损坏。MySQL提供了修复MySQL表的工具,不过对于敏感数据来说,支持ACID特性的InnoDB则是个更好的选择。
与之相反,PostgreSQL则是个只有单一存储引擎的完全集成的数据库。你可以通过调整postgresql.conf文件的参数来改进性能,也可以调整查询与事务。PostgreSQL文档对于性能调优提供了非常详尽的介绍。
MySQL与PostgreSQL都是高可配置的,并且可以针对不同的任务进行相应的优化。他们都支持通过扩展来添加额外的功能。
一个常见的误解就是MySQL要比PostgreSQL更容易学习。关系数据库系统都是非常复杂的,这两个数据库的学习曲线其实是差不多的。
标准兼容性
PostgreSQL旨在实现SQL兼容性(当前标准是ANSI-SQL:2008)。MySQL则兼容大部分SQL,不过还有自己的扩展,可以支持NoSQL特性,这在参考手册中都有介绍。每种方式都有优缺点。兼容标准会让数据库管理员、数据库开发者与应用开发者更舒服一些,因为这意味着他们只需学习一套标准、一套特性和命令即可。这会节省时间,提升效率,也不会被锁定在特定的厂商上。
支持使用非标准的自定义功能的人们认为这样可以快速采用新的特性,而不必等待标准进程完成。ANSI/ISO标准在不断演化,因此标准兼容性也是个变化的目标:知名的关系型数据库Microsoft SQL Server、Oracle与IBM DB2也只是部分兼容于标准。
结论
虽然有不同的历史、引擎与工具,不过并没有明确的参考能够表明这两个数据库哪一个能够适用于所有情况。很多组织喜欢使用PostgreSQL,因为它的可靠性好,在保护数据方面很擅长,而且是个社区项目,不会陷入厂商的牢笼之中。MySQL更加灵活,提供了更多选项来针对不同的任务进行裁剪。很多时候,对于一个组织来说,对某个软件使用的熟练程度要比特性上的原因更重要。
MySQL
MySQL声称自己是最流行的开源数据库。LAMP中的M指的就是MySQL。构建在LAMP上的应用都会使用MySQL,如WordPress、Drupal等大多数php开源程序。MySQL最初是由MySQL AB开发的,然后在2008年以10亿美金的价格卖给了Sun公司,Sun公司又在2010年被Oracle收购。Oracle支持MySQL的多个版本:Standard、Enterprise、Classic、Cluster、Embedded与Community。其中有一些是免费下载的,另外一些则是收费的。其核心代码基于GPL许可,由于MySQL被控制在Oracle,社区担心会对MySQL的开源会有影响,所以开发了一些分支,比如: MariaDB和Percona。
PostgreSQL
PostgreSQL标榜自己是世界上最先进的开源数据库。PostgreSQL的一些粉丝说它能与Oracle相媲美,而且没有那么昂贵的价格和傲慢的客服。最初是1985年在加利福尼亚大学伯克利分校开发的,作为Ingres数据库的后继。PostgreSQL是完全由社区驱动的开源项目。它提供了单个完整功能的版本,而不像MySQL那样提供了多个不同的社区版、商业版与企业版。PostgreSQL基于自由的BSD/MIT许可,组织可以使用、复制、修改和重新分发代码,只需要提供一个版权声明即可。
MySQL与PostgreSQL的对比
MySQL的背后是一个成熟的商业公司,而PostgreSQL的背后是一个庞大的志愿开发组。这使得MySQL的开发过程更为慎重,而PostgreSQL的反应更为迅速。这样的两种背景直接导致了各自固有的优点和缺点。
PostgreSQL相对于MySQL的优势
1)不仅仅是关系型数据库
除了存储正常的数据类型外,还支持存储:
array,不管是一位数组还是多为数组均支持
json(hStore)和jsonb,相比使用text存储接送要高效很多
json和jsonb之间的区别
jsonb和json在更高的层面上看起来几乎是一样的,但在存储实现上是不同的。
json存储完的文本,json列会每次都解析存储的值,它不支持索引,但你可以为查询创建表达式索引。
jsonb存储的二进制格式,避免了重新解析数据结构。它支持索引,这意味着你可以不使用指定的索引就能查询任何路径。
当我们比较写入数据速度时,由于数据存储的方式的原因,jsonb会比json稍微的慢一点。json列会每次都解析存储的值,这意味着键的顺序要和输入的时候一样。但jsonb不同,以二进制格式存储且不保证键的顺序。因此,如果你有软件需要依赖键的顺序,jsonb可能不是你的应用的最佳选择。使用jsonb的优势还在于你可以轻易的整合关系型数据和非关系型数据, PostgreSQL对于mongodb这类的基于文档的数据库是个不小的威胁,毕竟如果一个表中只有一列数据的类型是半结构化的,没有必要为了迁就它而整个表的设计采用schemaless的结构。
2)支持地理信息处理扩展
PostGIS 为PostgreSQL提供了存储空间地理数据的支持,使PostgreSQL成为了一个空间数据库,能够进行空间数据管理、数量测量与几何拓扑分析。在功能上,和MYSQL对比,PostGIS具有下列优势:
O2O业务场景中的LBS业务使用PostgreSQL + PostGIS有无法比拟的优势。
3)可以快速构建REST API
PostgREST 可以方便的为任何 PostgreSQL 数据库提供完全的 RESTful API 服务。
4)支持树状结构
支持R-trees这样可扩展的索引类型,可以更方便地处理一些特殊数据。MySQL 处理树状的设计会很复杂, 而且需要写很多代码, 而 PostgreSQL 可以高效处理树结构。
5)有极其强悍的 SQL 编程能力
支持递归,有非常丰富的统计函数和统计语法支持。
MySQL:支持 CREATE PROCEDURE 和 CREATE FUNCTION 语句。存储过程可以用 SQL 和 C++ 编写。用户定义函数可以用 SQL、C 和 C++ 编写。
PostgreSQL:没有单独的存储过程,都是通过函数实现的。用户定义函数可以用 PL/pgSQL(专用的过程语言)、PL/Tcl、PL/Perl、PL/Python 、SQL 和 C 编写。
6)外部数据源支持
可以把 70 种外部数据源 (包括 Mysql, Oracle, CSV, hadoop …) 当成自己数据库中的表来查询。Postgres有一个针对这一难题的解决方案:一个名为“外部数据封装器(Foreign Data Wrapper,FDW)”的特性。该特性最初由PostgreSQL社区领袖Dave Page四年前根据SQL标准SQL/MED(SQL Management of External Data)开发。FDW提供了一个SQL接口,用于访问远程数据存储中的远程大数据对象,使DBA可以整合来自不相关数据源的数据,将它们存入Postgres数据库中的一个公共模型。这样,DBA就可以访问和操作其它系统管理的数据,就像在本地Postgres表中一样。例如,使用FDW for MongoDB,数据库管理员可以查询来自文档数据库的数据,并使用SQL将它与来自本地Postgres表的数据相关联。借助这种方法,用户可以将数据作为行、列或JSON文档进行查看、排序和分组。他们甚至可以直接从Postgres向源文档数据库写入(插入、更细或删除)数据,就像一个一体的无缝部署。也可以对Hadoop集群或MySQL部署做同样的事。FDW使Postgres可以充当企业的中央联合数据库或“Hub”。
7)没有字符串长度限制
一般关系型数据库的字符串有限定长度8k左右,无限长 TEXT 类型的功能受限,只能作为外部大数据访问。而PostgreSQL的 TEXT 类型可以直接访问,SQL语法内置正则表达式,可以索引,还可以全文检索,或使用xml xpath。MySQL 的各种text字段有不同的限制,要手动区分 small text, middle text, large text… PostgreSQL 没有这个限制,text 能支持各种大小。
8)支持图结构数据存储
没有具体使用过,具体可以自己搜索下。参考链接:
9)支持窗口函数
窗口函数提供跨行相关的当前查询行集执行计算的能力。仅当调用跟着OVER子句的聚集函数,作为窗口函数;否则它们作为常规的聚合函数。窗口也是一种分组,但和 group by 的分组不同。窗口,可以提供分组之外,还可以执行对每个窗口进行计算。可以相像成是group by 后,然后对每个分组进行计算,而不像Group by ,只是单纯地分组。MySQL 不支持 OVER 子句, 而PostgreSQL支持。OVER 子句能简单的解决 “每组取 top 5” 的这类问题。MySQL支持的SQL语法(ANSI SQL标准)的很小一部分。不支持递归查询、通用表表达式(Oracle的with 语句)或者窗口函数(分析函数)。
10)对索引的支持更强
PostgreSQL 的可以使用函数和条件索引,这使得PostgreSQL数据库的调优非常灵活,mysql就没有这个功能,条件索引在web应用中很重要。对于索引类型:
MySQL:取决于存储引擎。MyISAM:BTREE,InnoDB:BTREE。
PostgreSQL:支持 B-树、哈希、R-树和 Gist 索引。
InnoDB的表和索引都是按相同的方式存储。也就是说表都是索引组织表。这一般要求主键不能太长而且插入时的主键最好是按顺序递增,否则对性能有很大影响。PostgreSQL不存在这个问题。
索引类型方面,MySQL取决于存储引擎。MyISAM:BTREE,InnoDB:BTREE。PostgreSQL支持 B-树、哈希、R-树和 Gist 索引。
11)集群支持更好
Mysql Cluster可能与你的想象有较大差异。开源的cluster软件较少。复制(Replication)功能是异步的并且有很大的局限性。例如,它是单线程的(single-threaded),因此一个处理能力更强的Slave的恢复速度也很难跟上处理能力相对较慢的Master。
PostgreSQL有丰富的开源cluster软件支持。plproxy 可以支持语句级的镜像或分片,slony 可以进行字段级的同步设置,standby 可以构建WAL文件级或流式的读写分离集群,同步频率和集群策略调整方便,操作非常简单。
另外,PostgreSQL的主备复制属于物理复制,相对于MySQL基于binlog的逻辑复制,数据的一致性更加可靠,复制性能更高,对主机性能的影响也更小。对于WEB应用来说,复制的特性很重要,mysql到现在也是异步复制,pgsql可以做到同步,异步,半同步复制。还有mysql的同步是基于binlog复制,类似oracle golden gate,是基于stream的复制,做到同步很困难,这种方式更加适合异地复制,pgsql的复制基于wal,可以做到同步复制。同时,pgsql还提供stream复制。
12)事务隔离做的更好
MySQL 的事务隔离级别 repeatable read 并不能阻止常见的并发更新, 得加锁才可以, 但悲观锁会影响性能, 手动实现乐观锁又复杂. 而 PostgreSQL 的列里有隐藏的乐观锁 version 字段, 默认的 repeatable read 级别就能保证并发更新的正确性, 并且又有乐观锁的性能。
13)对于字符支持更好一些
MySQL 里需要 utf8mb4 才能显示 emoji 的坑, PostgreSQL 没这个坑。
14)对表连接支持较完整
对表连接支持较完整,MySQL只有一种表连接类型:嵌套循环连接(nested-loop),不支持排序-合并连接(sort-merge join)与散列连接(hash join)。PostgreSQL都支持。
15)存储方式支持更大的数据量
PostgreSQL主表采用堆表存放,MySQL采用索引组织表,能够支持比MySQL更大的数据量。
16)时间精度更高
MySQL对于时间、日期、间隔等时间类型没有秒以下级别的存储类型,而PostgreSQL可以精确到秒以下。
17)优化器的功能较完整
MySQL对复杂查询的处理较弱,查询优化器不够成熟,explain看执行计划的结果简单。性能优化工具与度量信息不足。
PostgreSQL很强大的查询优化器,支持很复杂的查询处理。explain返回丰富的信息。提供了一些性能视图,可以方便的看到发生在一个表和索引上的select、delete、update、insert统计信息,也可以看到cache命中率。网上有一个开源的pgstatspack工具。
18)序列支持更好
MySQL 不支持多个表从同一个序列中取 id, 而 PostgreSQL 可以。
19)对子查询支持更好
对子查询的支持。虽然在很多情况下在SQL语句中使用子查询效率低下,而且绝大多数情况下可以使用带条件的多表连接来替代子查询,但是子查询的存在在很多时候仍然不可避免。而且使用子查询的SQL语句与使用带条件的多表连接相比具有更高的程序可读性。几乎任何数据库的子查询 (subquery) 性能都比 MySQL 好。
20)增加列更加简单
MySQL表增加列,基本上是重建表和索引,会花很长时间。PostgreSQL表增加列,只是在数据字典中增加表定义,不会重建表.
MySQL相对于PostgreSQL的优势
1)MySQL比PostgreSQL更流行
流行对于一个商业软件来说,也是一个很重要的指标,流行意味着更多的用户,意味着经受了更多的考验,意味着更好的商业支持、意味着更多、更完善的文档资料。易用,很容易安装。第三方工具,包括可视化工具,让用户能够很容易入门。
2)回滚实现更优
innodb的基于回滚段实现的MVCC机制,相对PG新老数据一起存放的基于XID的MVCC机制,是占优的。新老数据一起存放,需要定时触发VACUUM,会带来多余的IO和数据库对象加锁开销,引起数据库整体的并发能力下降。而且VACUUM清理不及时,还可能会引发数据膨胀。
3)在Windows上运行更可靠
与PostgreSQL相比,MySQL更适宜在Windows环境下运行。MySQL作为一个本地的Windows应用程序运行(在 NT/Win2000/WinXP下,是一个服务),而PostgreSQL是运行在Cygwin模拟环境下。PostgreSQL在Windows下运行没有MySQL稳定,应该是可以想象的。
4)线程模式相比进程模式的优势
MySQL使用了线程,而PostgreSQL使用的是进程。在不同线程之间的环境转换和访问公用的存储区域显然要比在不同的进程之间要快得多。
进程模式对多CPU利用率比较高。进程模式共享数据需要用到共享内存,而线程模式数据本身就是在进程空间内都是共享的,不同线程访问只需要控制好线程之间的同步。
线程模式对资源消耗比较少。所以MySQL能支持远比PostgreSQL多的更多的连接。但PostgreSQL中有优秀的连接池软件软件,如pgbouncer和pgpool,所以通过连接池也可以支持很多的连接。
5)权限设置上更加完善
MySQL在权限系统上比PostgreSQL某些方面更为完善。PostgreSQL只支持对于每一个用户在一个数据库上或一个数据表上的 INSERT、SELECT和UPDATE/DELETE的授权,而MySQL允许你定义一整套的不同的数据级、表级和列级的权限。对于列级的权限, PostgreSQL可以通过建立视图,并确定视图的权限来弥补。MySQL还允许你指定基于主机的权限,这对于目前的PostgreSQL是无法实现的,但是在很多时候,这是有用的。
6)存储引擎插件化机制
MySQL的存储引擎插件化机制,使得它的应用场景更加广泛,比如除了innodb适合事务处理场景外,myisam适合静态数据的查询场景。
7)适应24/7运行
MySQL可以适应24/7运行。在绝大多数情况下,你不需要为MySQL运行任何清除程序。PostgreSQL目前仍不完全适应24/7运行,这是因为你必须每隔一段时间运行一次VACUUM。
8)更加试用于简单的场景
PostgreSQL只支持堆表,不支持索引组织表,Innodb只支持索引组织表。
索引组织表的优势:表内的数据就是按索引的方式组织,数据是有序的,如果数据都是按主键来访问,那么访问数据比较快。而堆表,按主键访问数据时,是需要先按主键索引找到数据的物理位置。
索引组织表的劣势:索引组织表中上再加其它的索引时,其它的索引记录的数据位置不再是物理位置,而是主键值,所以对于索引组织表来说,主键的值不能太大,否则占用的空间比较大。
对于索引组织表来说,如果每次在中间插入数据,可能会导致索引分裂,索引分裂会大大降低插入的性能。所以对于使用innodb来说,我们一般最好让主键是一个无意义的序列,这样插入每次都发生在最后,以避免这个问题。
由于索引组织表是按一个索引树,一般它访问数据块必须按数据块之间的关系进行访问,而不是按物理块的访问数据的,所以当做全表扫描时要比堆表慢很多,这可能在OLTP中不明显,但在数据仓库的应用中可能是一个问题。
总结
MySQL从一开始就没有打算做所有事情,因而它在功能方面有一定的局限性,并不能满足一些先进应用程序的要求。MySQL对某些功能(例如引用、事务、审计等)的实现方式使得它与其他的关系型数据库相比缺少了一些可靠性。对于简单繁重的读取操作,使用PostgreSQL可能有点小题大做,同时性能也比MySQL这样的同类产品要差。除非你需要绝对的数据完整性,ACID遵从性或者设计复杂,否则PostgreSQL对于简单的场景而言有点多余。
如何你确定只在MySQL和PostgreSQL中进行选择,以下规则总是有效的:
如果你的操作系统是Windows,你应该使用MySQL。
当绝对需要可靠性和数据完整性的时候,PostgreSQL是更好的选择。
如果需要数据库执行定制程序,那么可扩展的PostgreSQL是更好的选择。
你的应用处理的是地理数据,由于R-TREES的存在,你应该使用PostgreSQL。
如果你对数据库并不了十分了解,甚至不知道事务、存储过程等究竟是什么,你应该使用MySQL。
邹锐的回复比较官方,我就用个软件攻城狮的口气解释一下吧
MySQL用的比较多吧,可能用Mysql的公司比PostgreSQL要多一些,而且MySql的服务也很多,额,这些其实都不重要,重要的是你的程序端是什么,比喻C#和SqlServer这天生一对,还有MySql和PHP,Oracle 和C++这些配对都挺不错,当然PostgreSQL也比较有名气,只要写好Dll或者下载一个组件,C#的WinForm也可以用,可能C++也不错,当然Java把接口做好也可以,但是我对这个数据库不熟悉,我还是比较熟悉MySQL,查询比较快,这也是很多公司用他的原因,我也用过几次,但是最后还是选择了SqlServer,因为很多程序都支持他,数据库的脚步大多一样,包括什么存储过程啊,提交事物啊,视图,索引,触发器之类的,只要用好了一个,其他的大多无师自通了,关键还是自己的程序端是什么,功能是什么,数据量有多少,相信你也很清楚数据库的关键性,毕竟合适的数据库是程序端一个强大的后盾啊,说了堆没用的,其实我对PostgreSQL了解不多,他既然能开源自然是有厚底子,MySql的综合实力应该比不上他,毕竟是小数据库,速度也好,使用率也好,都是表面的,PostgreSQL是元老,和SqlServer是一个年代的,敢开源的东西都应该得到尊重的,不像SqlServer收费,最后说形象点吧,PostgreSQL是C,MySql是Java;PostgreSQL是HTML,MySql是PHP,PostgreSQL是经验丰富的项目经理,Mysql是年轻的软件工程师...