Mysql空间索引

Mysql空间索引,第1张

在涉及LBS的服务开发过程中,经常需要存储地理空间的位置并进行一定计算(附近商家等需求),本文主要介绍mysql对于LBS的支持。

Mysql的空间扩展主要提供一下几个方面的功能:

其中前两点对InnoDB,MyISAM,NDB,ARCHIVE等mysql存储引擎都支持,第三点只有对InnoDB和MyISAM的支持,由于InnoDB的支持行锁以及事务的特性,现在基本上已经是默认存储引擎了,所以本文以下内容都默认使用InnoDB。

创建空间列以及空间索引的语句如下:

Mysql的空间数据类型与OpenGIS的数据类型相对应。

Mysql的空间数据有不同表示格式,其中咱能看懂的也就第一种

因为上文提到了SRID,这里说下什么是SRID,SR是指Spatial Reference,也就是我们常说的空间参考系,mysql支持卡迪尔坐标系和地理坐标系,其中地理坐标系又有好多种,下面说几种常用的空间参考系

Mysql的所有空间坐标系都存在表 mysql.st_spatial_reference_system 中,这个表是隐藏的,看不见的,但是你可以通过 infomation_shcema.st_spatial_reference_system 中查看参考系的信息,这个表就是 mysql.st_spatial_reference_system 的一个视图的实现。

mysql的空间索引的数据结构是R树,R树实际上就是多维的B树,B树的数据结构在我的另一篇博客中有介绍,这里就不展开了,说几点在应用的时候需要注意的。

最后转一篇博文 https://visonforcoding.github.io/di-li-wei-zhi-geochu-li-zhi-mysql-geo-suo-yin.html

探索和学习MySQL中GIS相关功能和特性

这里记录了学习和了解MySQL中GIS特性相关内容的过程。

MySQL官方论坛中GIS的举例

测试数据已经导入成功,下面开始对GIS相关函数和GEOHASH进行了解和体验;

mysql中geometry类型的简单使用

MySQL空间数据类型

经纬度信息存储在geometry格式的字段中,该字段必须非空。

MySQL8.0前按照longitude-latitude的顺序存储位置

MySQL8.0前按照longitude-latitude的顺序存储位置

MySQL8.0前按照longitude-latitude的顺序存储位置

插入数据时候可使用如下语句:

MySQL存储geometry信息的方式采用了25bytes,相比WKB的21bytes,多了4bytes的坐标系表示,组成部分如下:

WTF字符串格式说明

select ST_GeomFromText(WTF格式字符串)

WKT(Well-known text)是一种文本标记语言,用于表示矢量几何对象、空间参照系统及空间参照系统之间的转换。通过WTF字符串生成geometry的方法:

点: POINT(x y)

线: LINESTRING(x1 y1, x2 y2, x3 y3...)

多边形: POLYGON((0 0, 10 0, 10 10,0 10,0 0),(5 5,7 5,7 7,5 7,5 5))

多点集: MULTIPOINT(0 0, 20 20, 60 60) 或 MULTIPOINT((0 0),(5 5),(5 0))

多线集: MULTILINESTRING((10 10, 20 20), (15 15, 30 15))

多多边形集: MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0)),((5 5,7 5,7 7,5 7, 5 5)))

例如两点一线组成的几何集: GEOMETRYCOLLECTION(POINT(10 10), POINT(30 30), LINESTRING(15 15, 20 20))

A geometry is syntactically well-formed if it satisfies conditions such as those in this (nonexhaustive) list:

Collections are not empty (except GeometryCollection)

更多内容参见

ST_PointFromText('POINT(X Y)')

ST_LineStringFromText('LINESTRING(0 0,1 1,2 2)')

ST_PolygonFromText('POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7,5 5))')

ST_GeomCollFromText()

更多内容参见

参见

Point(x,y)

LineString((x1,y1),(x2,y2)...)

Polygon(LineString(),LineString()....)

参见

ST_AsText()

ST_AsBinary()

ST_AsWKT()

参见

ST_Dimension(geom) :返回geom的维度(-1,0,1,2)

ST_Envelope(geom) :返回geom的最小外接矩形(MBR)

ST_GeometryType(geom) :返回geom的类型

ST_IsEmpty(geom) :该函数并不能真实的判空,当geom为任何有效的几何值时返回0,无效的几何值返回1;

ST_IsSimple(geom) :当geom无任何异常几何点返回1(如自相交和自切线等),否则返回0

ST_SRID(geom) :返回geom的坐标系ID

参见

ST_X(Point) :获取Point的X值

ST_Y(Point) :获取Point的Y值

参见

ST_StartPoint(linestrng) : 线的起点

ST_EndPoint(linestring) :返回线的最后一个点

ST_IsClosed(linestring或multilinestring) :线是否闭合(若为线,则判断起点与终点是否一致;若为线组,则判断组内每个元素是否符合闭合线)

ST_Length(linestring) :返回线的长度,若入参为线集,则返回集合内所有长度的和

ST_NumPoiints(linestring) :返回点的数量;

ST_PointN(linestring,N) :返回第N个点(从1开始)

参见

具体不在一一列举,主要有计算多边形面积、中心点、最小外接圆,最大内接圆等函数,列举几个可能会用到的:

ST_Area(Poly|mPoly) :返回双精度的面积或面积的和

'ST_Centroid(Poly|mPoly)':返回数学上的中心点

ST_ExteriorRing(Poly) :返回外接圆

参见

ST_Buffer说明

不再列举,主要有:ST_Buffer(不懂干啥用),ST_ConvexHull(geom)凸包,ST_Dfference(g1,g2)比较差异,ST_Intersecton(g1,g2)交叉点,ST_SymDifference(g1,g2)对称差分,ST_Union(g1,g2)连接、合并等。

检查geometry Objects之间的空间关系的方法。

参见

计算两个Object之间的空间关系的函数,有两个间距离、相交、不相交,包含、相等、相切、重叠、接触、在内等等空间关系。下面列举几个可能会常用的方法:

ST_Contains(g1,g2) :g1是否完全包含g2

ST_Within(g1,g2) :g1是否包含于g2中

ST_Distance(g1,g2) :返回g1和g2之间的距离,已坐标单位计算的

ST_Equals(g1,g2) :返回g1和g2是否相等

参见

MBRContains(g1,g2) :g1的mbr是否包含g2的mbr

MBRWithin(g1,g2) :g1的mbr是否在g2的mbr内

MBRCoveredBy(g1,g2) :g1的mbr是否被g2的mbr覆盖

MBRCovers(g1,g2) :g1的mbr是否覆盖g2的mbr

MBRDisjoint(g1,g2) :g1的mbr,g2的mbr是否不相交

MBRIntersects(g1,g2) :g1mbr,g2mbr是否相交

MBREqual(g1,g2) :g1的mbr,g2的mbr的外接是否相等

MBREquals(g1,g2) :g1的mbr,g2的mbr的外接是否相等

MBROverlaps(g1,g2) :g1mbr、g2mbr

其他函数请参看原文

GeoHash介绍

GeoHash Wiki百科

MySQL中自带函数 st_geohash(longtude,latitude,max_length) 或 st_geohash(point, max_length) 即可生成某一点的geohash值。

返回一个geohash字符串中的latitude或longitude

返回一个geohash解析出的point数据

官方文档

通过geometry生成一个GeoJSON Object, select st_asgeojson(geometry,max_length,options)

通过GeoJSON生成GeoMetry对象。

ST_GeomFromGeoJSON(jsonstring, [options [, srid]])

具体使用方法参见官方文档

官方文档

MySQL中提供的方便空间运算的函数们

select ST_Distance_Spher(geomPoint1,geomPoint2 [, radius])

此方法用于计算两点或多个点之间的地球上的距离(是地球球面距离而不是直线距离),返回单位为米,

select ST_IsValid(ST_GeomFromText('LINESTRING(0 0,1 1)'))

判断入参是否是符合地理位置描述的格式。返回1(符合)或者0(不符);

例如:

返回0:

select st_isvalid(st_geomfromtext('linestring(0 0, -0.00 0, 0.0 0)')

返回1:

select st_isvalid(st_geomfromtext('linestring(0 0,1 1)')

select st_astext(st_makeenvelope(pt1, pt2))

返回两点构成的包络。(此计算是基于笛卡尔坐标系而非球面)

例如:

SELECT ST_AsText ( st_makeenvelope ( st_geomfromtext ( 'point(0 0)' ), st_geomfromtext ( 'point(1 1)' ) ) )

返回结果:

POLYGON((0 0,1 0,1 1,0 1,0 0))

效果说明

JS抽稀算法

select st_simplify(geometry, max_distance)

用道格拉斯-普克算法(抽稀函数)简化geometry,并返回与原格式相同格式的结果。

例如,以下点集拟合为直线,步长0.5:

SELECT st_simplify ( st_geomfromtext ( 'LINESTRING(0 0,0 1,1 1,1 2,2 2,2 3,3 3)' ), 0.5 )

返回结果:

LINESTRING(0 0, 0 1, 1 1, 2 3, 3 3)

再如,步长1.0:

SELECT st_simplify ( st_geomfromtext ( 'LINESTRING(0 0,0 1,1 1,1 2,2 2,2 3,3 3)' ), 1.0 )

返回结果:

LINESTRING(0 0, 3 3)

SELECT ST_Validate(geometry)

验证geometry是符合正确的地理位置信息格式。例如 Point(0 0) 是合格的; Linestring(0 0) 是非法的; Linestring(0 0, 1 1) 是合格的

了解了上述MySQL中关于集合对象的功能,下面来实践一下

由上面geohash长度-精度对应表可知,前6位表示±610米左右的误差,这里先查询前六位范围之后再用上述方法精确筛选一次即可:

可将上述查询方法封装为MySQL函数方便和简化程序调用.

该方法是运用了内置的几何关系运算函数 ST_Contains 和 ST_MakeEnvelop 来实现的,0.5对应大概500米左右的范围,具体如下;

链接: https://pan.baidu.com/s/1cW-kv6DIgtYMw5I3bNFzKA

提取码: jagn

INSERT INTO mt_message (`id`,`name` ,`tel` ,`email` )VALUES (NULL,'111111111', '11', '1')

INSERT INTO mt_message(`id` ,`name` ,`tel` ,`email` ,`qita` ,`content` ,`shijian` ,`user` ,`huifu` ,`shenhe`

//)VALUES (NULL , '1', '2', '', '', '', NOW( ) , '', '', '')

只能说明:你从email开始后面的字段其中有一个是不能为空的,而且没有初始值

所以你第一个语句插入失败了

我估计应该问题就是在你的时间(shijian)字段,因为后面基本都是空的,只有时间不是

你可以去检查一个你的这张message表,在mysql命令行用:desc message

检查数据表的字段名和字段属性,如果不行你可以重新建立数据表的

要是想知道出错在哪里,你可以这样写:

<?php

//..上面程序略

$sql="INSERT INTO mt_message (`id`,`name` ,`tel` ,`email` )VALUES (NULL,'111111111', '11', '1')"

$query=mysql_query($sql)

//执行

if($query)

//执行成功

echo 'OK'

else

echo '插入失败,错误报告是:'.mysql_error()

//输出mysql错误信息函数:mysql_error()

?>

如果还有不懂可以Hi我,我很乐意教的


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/7669041.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-08
下一篇 2023-04-08

发表评论

登录后才能评论

评论列表(0条)

保存