MySQL Spatial Extensions 地理信息
http://dev.mysql.com/doc/refman/5.7/en/gis-data-formats.html
http://mysqlserverteam.com/mysql-5-7-and-gis-an-example/
最好的Spatial Database(空间数据库)当然是Oracle家的,可惜没用过。最好的开源的Spatial Database一般公认是PostGIS,以前用过一阵子,安装特别麻烦,不过各种功能很齐全。前段时间尝试了一下MySQL的spatial extensions,下面记录了一些使用心得:
1. MySQL Spatial Extensions(后面简称MySQL Spatial)功能不够完全。至少和PostGIS相比是这样的,它只支持了openGIS(一个标准)的一个子集,包涵有限的几种空间数据类型(比如Point,LineString,Polygon等),支持的函数也很少,比如,连计算两个点的distance函数都没有...
2. MySQL Spatial的安装配置非常的简单。其实,它根本不需要安装。默认的MySQL配置就能够使用这些空间数据类型。这和PostGIS很不一样,PostGIS是需要在PostgreSQL上再安装一个扩展包。
3. 不同的存储引擎有差别。MyISAM和InnoDB都支持spatial extensions,但差别在于:如果使用MyISAM,可以建立spatial index,而InnoDB是不支持的。这点差别在某些场景下很关键,后面会再详细说说spatial index。
4. POINT的使用。点是最基本也是最常用的一种空间数据类型。MySQL Spatial中用POINT表示点,比如,可以创建一个table:
mysql 5.7
CREATE TABLE address (
address CHAR(80) NOT NULL,
address_loc POINT NOT NULL,
PRIMARY KEY(address),
SPATIAL KEY(address_loc)
);
show craate table address CREATE TABLE `address` (
`address` char(80) NOT NULL,
`address_loc` point NOT NULL,
PRIMARY KEY (`address`),
SPATIAL KEY `address_loc` (`address_loc`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8'
其中,address_loc就是一个point类型,说明address_loc是一个点。
插入一个点:
INSERT INTO address VALUES('Foobar street 12', GeomFromText('POINT(2671 2500)'));
INSERT INTO address VALUES('Foobar street 13', ST_GEOMFROMTEXT ('POINT(2670 2500)'));
读取一个点:
select AsText(address_loc) from address;
# AsText(address_loc)
'POINT(2671 2500)'
'POINT(2670 2500)'
分离点X,Y
set @p = GeomFromText('POINT(11 0)');
select x(@p), y(@p);
# x(@p) y(@p)
The OpenGIS Geometry Model
The Geometry Class Hierarchy
Geometry Class
Point Class
Curve Class
LineString Class
Surface Class
Polygon Class
GeometryCollection Class
MultiPoint Class
MultiCurve Class
MultiLineString Class
MultiSurface Class
MultiPolygon Class
Supported Spatial Data Formats
Two standard spatial data formats are used to represent geometry objects in queries: Well-Known Text (WKT) format Well-Known Binary (WKB) format
mysql> SELECT ST_X(Point(15, 20));
+---------------------+
| ST_X(Point(15, 20)) |
+---------------------+
| 15 |
+---------------------+
1 row in set (0.00 sec)
mysql> SELECT ST_Y(Point(15, 20));
+---------------------+
| ST_Y(Point(15, 20)) |
+---------------------+
| 20 |
+---------------------+
1 row in set (0.00 sec)
Fetching Spatial Data
Geometry values stored in a table can be fetched in internal format. You can also convert them to WKT or WKB format. Fetching spatial data in internal format: Fetching geometry values using internal format can be useful in table-to-table transfers: CREATE TABLE geom2 (g GEOMETRY) SELECT g FROM geom;
Fetching spatial data in WKT format: The ST_AsText() function converts a geometry from internal format to a WKT string. SELECT ST_AsText(g) FROM geom;
Fetching spatial data in WKB format: The ST_AsBinary() function converts a geometry from internal format to a BLOB containing the WKB value. SELECT ST_AsBinary(g) FROM geom;
CREATE TABLE geom (g GEOMETRY);
insert into geom select point(1,2);
SELECT ST_AsText(g) FROM geom;
SELECT ST_AsBinary(g) FROM geom;
Populating Spatial Columns
After you have created spatial columns, you can populate them with spatial data. Values should be stored in internal geometry format, but you can convert them to that format from either Well-Known Text (WKT)
or Well-Known Binary (WKB) format. The following examples demonstrate how to insert geometry values into a table
by converting WKT values to internal geometry format: Perform the conversion directly in the INSERT statement: INSERT INTO geom VALUES (ST_GeomFromText('POINT(1 1)')); SET @g = 'POINT(1 1)';
INSERT INTO geom VALUES (ST_GeomFromText(@g));
Perform the conversion prior to the INSERT: SET @g = ST_GeomFromText('POINT(1 1)');
INSERT INTO geom VALUES (@g);
The following examples insert more complex geometries into the table: SET @g = 'LINESTRING(0 0,1 1,2 2)';
INSERT INTO geom VALUES (ST_GeomFromText(@g)); SET @g = 'POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))';
INSERT INTO geom VALUES (ST_GeomFromText(@g)); SET @g =
'GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))';
INSERT INTO geom VALUES (ST_GeomFromText(@g));
The preceding examples use ST_GeomFromText() to create geometry values. You can also use type-specific functions: SET @g = 'POINT(1 1)';
INSERT INTO geom VALUES (ST_PointFromText(@g)); SET @g = 'LINESTRING(0 0,1 1,2 2)';
INSERT INTO geom VALUES (ST_LineStringFromText(@g)); SET @g = 'POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))';
INSERT INTO geom VALUES (ST_PolygonFromText(@g)); SET @g =
'GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))';
INSERT INTO geom VALUES (ST_GeomCollFromText(@g));
A client application program that wants to use WKB representations of geometry values is responsible for sending correctly formed WKB
in queries to the server. There are several ways to satisfy this requirement. For example: Inserting a POINT(1 1) value with hex literal syntax: mysql> INSERT INTO geom VALUES
-> (ST_GeomFromWKB(0x0101000000000000000000F03F000000000000F03F));
An ODBC application can send a WKB representation, binding it to a placeholder using an argument of BLOB type: INSERT INTO geom VALUES (ST_GeomFromWKB(?))
Other programming interfaces may support a similar placeholder mechanism.
一个比较麻烦的问题是,如何计算两个POINT的距离?之前说过了,MySQL Spatial不提供distance这个函数。官方指南的做法是这样的:
GLength(LineStringFromWKB(LineString(point1, point2)))
这条语句大概的意思是用两个点产生一个LineString的类型,然后调用GLength得到line的长度。
这么做,也对也不对。
对是因为它确实计算的是距离,但是,这种方法计算的是欧式空间的距离。或者简单的说,它计算的是直线距离。如果两个点是地理坐标,比如point(116.34, 39.28),想计算地理位置的距离,那么这样做肯定就不对了。正确的做法应该是使用专门计算地理位置的公式。
5. MySQL Spatial Index的使用。使用这样的语句:
ALTER TABLE address ADD SPATIAL INDEX(address_loc);
可以在空间数据类型上创建一个spatial index,这个功能只有MyISAM才支持。Index的本质实际上是一个R-TREE,这也是最常用来作为多维数据索引的数据结构。
那么,该如何使用这个index?
举例来说,假设需要查找某个矩形区域内所有的点,一种方法是这样:
select * from address where (X(address_loc) > 116.3952) AND (X(address_loc) < 116.4052) AND (Y(address_loc) > 39.8603) AND (Y(address_loc) < 39.8703);
假设我们已经在address_loc这个column上创建了spatial index,所以上述的查询应该很快。不幸的是,这不是事实。上述的查询会扫描table内的所有数据,挨个进行计算,建立的index完全不起作用。
正确的做法是,在查询中使用一些内建的和spatial有关的函数,只有这些函数能够有效的利用到index。比如,正确的查询应该是:
select AsText(address_loc) from address where MBRContains(GeomFromText(Polygon((115.3073 40.3821, 115.3173 40.3821, 115.3173 40.4021, 115.3073 40.4021, 115.3073 40.3821))),address_loc);
这里用到了函数MBRContains,用于判断一个point是否在指定的polygon内部。这个函数就能够很好的使用之前创建的spatial index。可以做个试验,比较之前两个查询的处理时间,你会发现,后者的速度要快很多。
总的来说,如果只需要做一些简单的GIS或者LBS的应用,MySQL提供的spatial extensions能够满足。但如果需要的功能更复杂一些,MySQL spatial extensions提供的功能可能就不够用了,需要在MySQL之上自己实现更多的逻辑,或者换成PostGIS。
MySQL Spatial Extensions 地理信息的更多相关文章
- Extensions for Spatial Data
http://dev.mysql.com/worklog/task/?spm=5176.100239.blogcont4270.8.j3asa7&id=6609 前文: 这两天因为项目原因看了 ...
- Mysql 地区经纬度 查询
摘要: Mysql数据库,根据地区的经纬度信息,查询附近相邻的地区 2015-03-27 修改,增加 MySQL的空间扩展(MySQL Spatial Extensions)的解决方案: MySQL的 ...
- mysql空间扩展 VS PostGIS
http://www.cnblogs.com/LBSer/p/3629149.html 功能 Mysql spatial extension PostGIS 空间索引 仅MyISAM支持R树索引,I ...
- 深入浅出Symfony2 - 结合MongoDB开发LBS应用
简介 随着近几年各类移动终端的迅速普及,基于地理位置的服务(LBS)和相关应用也越来越多,而支撑这些应用的最基础技术之一,就是基于地理位置信息的处理.我所在的项目也正从事相关系统的开发,我们使用的是S ...
- 结合MongoDB开发LBS应用
然后列举一下需求:1.实时性要高,有频繁的更新和读取2.可按距离排序支持分页3.支持多条件筛选(一个经纬度数据还包含其他属性,比如社交系统的性别.年龄) 方案简单介绍:1.sphinx geo索引支持 ...
- 结合MongoDB开发LBS应用(转)
原文链接:结合MongoDB开发LBS应用 简介 随着近几年各类移动终端的迅速普及,基于地理位置的服务(LBS)和相关应用也越来越多,而支撑这些应用的最基础技术之一,就是基于地理位置信息的处理.我所在 ...
- MySQL开发总结(有点长..耐心看)
一.理解MySQL基本概念 1.MySQL软件:MySQL实际上就是一软件,是一工具,是关系型数据库管理系统软件 2.MySQL数据库:就是按照数据结构来组织.存储和管理数据的仓库 3.MySQL数据 ...
- mysql开发总结
一.理解MySQL基本概念 1.MySQL软件:MySQL实际上就是一软件,是一工具,是关系型数据库管理系统软件 2.MySQL数据库:就是按照数据结构来组织.存储和管理数据的仓库 3.MySQL数据 ...
- Mysql 和 Postgresql(PGSQL) 对比
Mysql 和 Postgresql(PGSQL) 对比 转载自:http://www.oschina.net/question/96003_13994 PostgreSQL与MySQL比较 MySQ ...
随机推荐
- HDU2648:Shopping(DKBR_hash)
题目链接 题意: 给出n个字符串,接下来m天,每天每个字符串要增加对应的值,询问“memory”每天的排名 分析: 用hash表hash出每个字符串对应得值,然后放入二维数组(防止地址冲突),m天,输 ...
- Xcode升级后插件失效的原理与修复办法
转载:http://joeshang.github.io/2015/04/10/fix-xcode-upgrade-plugin-invalid/ Xcode 的插件大大丰富了 Xcode 的功能,而 ...
- 构建Spark作业
首先,要清楚,一个Java或Scala或python实现的Spark作业. 1.用sbt构建Spark作业 2.用Maven构建Spark作业 3.用non-maven-aware工具构建Spark作 ...
- resharper 7.x 注册码key
user:dobit sn:G/YgFyekI7EL0oBc5YBWKI5WCi3pwXWP
- Python基础 条件、循环
1.条件语句 Python条件语句是通过一条或多条语句的执行结果(True或者False)来决定执行的代码块. if if语句执行有个特点,它是从上往下判断,如果在某个判断上是True,把该判断对应的 ...
- Javascript模块规范(CommonJS规范&&AMD规范)
Javascript模块化编程(AMD&CommonJS) 前端模块化开发的价值:https://github.com/seajs/seajs/issues/547 模块的写法 查看 AMD规 ...
- Android中全局Application的onCreate多次调用问题
String processName = OsUtils.getProcessName(this, android.os.Process.myPid()); if (processName != nu ...
- 详解MyEclipse10 安装Spket 1.6.23(支持Extjs4.1.1及jQuery1.8)
用MyEclipse10安装Spket主要有3种方式:在线下载更新.下载Zip覆盖.下载jar包安装.我用在线安装尝试了N次终于还是失败,只好下载jar包来安装,在失败了M次之后终于安装成功,现在网上 ...
- JavaScript闭包——实现
闭包的官方的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. 通俗点的说法是: 从理论角度:所有的函数.因为它们都在创建的时候就将上层上下文 ...
- cocos2d-x 如何保持屏幕常亮
转自:http://blog.csdn.net/wolfking_2009/article/details/8939027 貌似cocos2d-x没有接口直接做这个功能 而各个平台又不一样,所以只能对 ...