Mysql 空間索引
本文主要根據(jù)mysql 8.0的文檔翻譯總結(jié),如果使用的是mysql 5.7版本,可能會有些許差異
在涉及LBS的服務(wù)開發(fā)過程中,經(jīng)常需要存儲地理空間的位置并進(jìn)行一定計(jì)算(附近商家等需求),本文主要介紹mysql對于LBS的支持。
Mysql的空間擴(kuò)展主要提供一下幾個(gè)方面的功能:
- 表示空間數(shù)值的數(shù)據(jù)類型
- 操作空間數(shù)值的函數(shù)
- 空間索引,用于提供訪問空間列的速度
其中前兩點(diǎn)對InnoDB,MyISAM,NDB,ARCHIVE等mysql存儲引擎都支持,第三點(diǎn)只有對InnoDB和MyISAM的支持,由于InnoDB的支持行鎖以及事務(wù)的特性,現(xiàn)在基本上已經(jīng)是默認(rèn)存儲引擎了,所以本文以下內(nèi)容都默認(rèn)使用InnoDB。
創(chuàng)建空間列以及空間索引的語句如下:
CREATE TABLE geom (g GEOMETRY NOT NULL SRID 4326, SPATIAL INDEX(g));
Mysql空間數(shù)據(jù)類型
Mysql的空間數(shù)據(jù)類型與OpenGIS的數(shù)據(jù)類型相對應(yīng)。
-
單一幾何值的空間數(shù)據(jù)類型:
- GEOMETRY
- POINT
- LINESTRING
- POLYGON
其中GEOMETRY可以存儲任意類型的集合類型,POINT LINESTRING POLYGON則限制了集合類型
-
空間集合數(shù)據(jù)類型:
- MULTIPOINT
- MULTILINESTRING
- MULTIPOLYGON
- GEOMETRYCOLLECTION
空間數(shù)據(jù)類型的表示形式
Mysql的空間數(shù)據(jù)有不同表示格式,其中咱能看懂的也就第一種
Well-known Text Format (WKT)形如 Point(1 1)
-
Well-know Binary Format (WKB) 二進(jìn)制表示,貼下幀結(jié)構(gòu),自己感受下
Component Size Value Byte order 1 byte 01WKB type 4 bytes 01000000X coordinate 8 bytes 000000000000F03FY coordinate 8 bytes 000000000000F0BF -
Mysql內(nèi)部幾何存儲結(jié)構(gòu)
就是在WKB的前面加上4個(gè)字節(jié)來表示SRID,就變成了mysql存儲的數(shù)據(jù)結(jié)構(gòu)
什么是SRID
因?yàn)樯衔奶岬搅薙RID,這里說下什么是SRID,SR是指Spatial Reference,也就是我們常說的空間參考系,mysql支持卡迪爾坐標(biāo)系和地理坐標(biāo)系,其中地理坐標(biāo)系又有好多種,下面說幾種常用的空間參考系
-
SRID=0表示一個(gè)無限的卡迪爾坐標(biāo)系平面,且坐標(biāo)軸上無單位 -
SRID=4326表示GPS坐標(biāo)系 -
SRID=3857是web地圖投影,就是你在谷歌地圖上看到的坐標(biāo)系
ALTER TABLE geom ADD position POINT SRID 4326
Mysql的所有空間坐標(biāo)系都存在表mysql.st_spatial_reference_system中,這個(gè)表是隱藏的,看不見的,但是你可以通過infomation_shcema.st_spatial_reference_system中查看參考系的信息,這個(gè)表就是mysql.st_spatial_reference_system的一個(gè)視圖的實(shí)現(xiàn)。
mysql> select * from information_schema.st_spatial_reference_systems where srs_id=4326;
+----------+--------+--------------+--------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------+
| SRS_NAME | SRS_ID | ORGANIZATION | ORGANIZATION_COORDSYS_ID | DEFINITION | DESCRIPTION |
+----------+--------+--------------+--------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------+
| WGS 84 | 4326 | EPSG | 4326 | GEOGCS["WGS 84",DATUM["World Geodetic System 1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.017453292519943278,AUTHORITY["EPSG","9122"]],AXIS["Lat",NORTH],AXIS["Lon",EAST],AUTHORITY["EPSG","4326"]] | NULL |
+----------+--------+--------------+--------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------+
1 row in set (0.00 sec)
SRS的解析是在GIS函數(shù)調(diào)用后才會去懶加載,并把解析的地理位置定義緩存到數(shù)據(jù)字典中,以后每次需要SRS的信息時(shí)不會重復(fù)解析
操作空間數(shù)據(jù)
-
插入數(shù)據(jù)
INSERT INTO geom VALUES (ST_GeomFromText('POINT(1 1)')) -
查詢內(nèi)部數(shù)據(jù)結(jié)構(gòu)
SELECT g FROM geom -
查詢WKT
SELECT ST_AsText(g) FROM geom -
查詢WKB
SELECT ST_AsBinary FROM geom
此外常用的還有ST_X,ST_Y,有需要可以去從手冊上查
空間索引
mysql的空間索引的數(shù)據(jù)結(jié)構(gòu)是R樹,R樹實(shí)際上就是多維的B樹,B樹的數(shù)據(jù)結(jié)構(gòu)在我的另一篇博客中有介紹,這里就不展開了,說幾點(diǎn)在應(yīng)用的時(shí)候需要注意的。
- 建立空間索引需要對應(yīng)列NOT NULL且有具體的SRID,沒有SRID屬性的列稱為非SRID約束,會接收任何SRID坐標(biāo)系的值,但是優(yōu)化器不能再這樣沒有SRID的列上使用空間索引
- 空間索引只能建立在空間數(shù)據(jù)類型上
- 如果在不支持空間索引的存儲引擎中對非空間列建立索引,則會建立B樹索引,可以用于精確查找空間位置,但是不能范圍查找(把空間數(shù)據(jù)列當(dāng)成字符串去建立索引)
最后轉(zhuǎn)一篇博文 https://visonforcoding.github.io/di-li-wei-zhi-geochu-li-zhi-mysql-geo-suo-yin.html