簡述
MySQL在5.7之后的版本支持了空間索引,而且支持OpenGIS幾何數據模型。國內的MySQL相關的書籍都比較老了,在這方面有詳細描述的還沒有見過。有一本比較新的PostgreSQL的數據介紹過空間搜索相關的內容,但是也不夠詳細。所以對於這方面的內容,不管是MySQL還是PostgreSQL,都建議直接去看官方文檔,都有很詳細的示例。
參考資料:
- MySQL官方文檔主頁
- MySQL5.7版本空間數據參考文檔
- MySQL支持的空間數據格式
- 12.16.1 Spatial Function Reference
- 空間索引和 ST_Geometry
- ST_Geometry 的關系函數
MySQL在空間索引這方面遵循OpenGIS幾何數據模型規則,詳情可見
- MySQL中 OpenGIS Geometry Model
- OpenGIS Implementation Specification for Geographic information - Simple feature access - Part 2: SQL option
下面記錄一下簡單的使用。
1、創建一個帶有空間索引的表
我這里主要是用於檢索遙感影像數據的,這里就只創建了兩個字段,一個是影像路徑path
,一個是有效外包框box
。
CREATE TABLE `gim` (
`path` varchar(512) NOT NULL,
`box` geometry NOT NULL,
PRIMARY KEY (`path`),
SPATIAL KEY `box` (`box`)
) ;
這里創建好之后,就可以往里面插入數據了。
2、插入數據
數據的插入和普通的數據插入一樣,只是geometry
數據需要使用st_geomfromtext
等函數來構造,相關的文檔參考在這里gis-data-formats還有這個populating-spatial-columns。
這里只展示一個簡單數據插入,這里我使用的是單多邊形,只有四個點(逆時針順序),使用WKT描述幾何數據。
insert into gim (path,box) values('%s',ST_GeomFromText(
'Polygon((116.18866 39.791107, 116.124115 39.791107, 116.18866 39.833679, 116.124115 39.833679, 116.18866 39.791107))'));
我這里寫了個程序,插入了上千條數據,方便后面的搜索。
3、查詢數據
查詢這里和普通的查詢也一樣,只是where
字句后面使用空間過濾相關選項就是。
使用空間索引進行查詢的相關文檔在這里using-spatial-indexes
MySQL的文檔中只提及了MBRContains
和MBRWithin
兩種方式,經過測試,MBRIntersects
、MBREqual
、MBROverlaps
、MBRTouches
、MBRDisjoint
都可以使用。
SpatiaLite中有一幅關於空間檢索的圖,放在這里做個參考。
SpatiaLite有一篇詳細介紹空間索引的文檔,鏈接在這里http://www.gaia-gis.it/spatialite-2.1/SpatiaLite-manual.html
一個簡單的查詢示例:
select * from gim where MBRContains(st_geomfromtext('polygon((116.438599 39.832306, 116.374054 39.832306, 116.438599 39.876251, 116.374054 39.876251, 116.438599 39.832306))'),box);
返回結果如下:
+------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------+
| path | box |
+------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------+
| file:///root1/北京/北京分区/æœé˜³åŒº/æœé˜³åŒº2016/J50G004039.tif | POLYGON((116.438599 39.832306, 116.374054 39.832306, 116.438599 39.876251, 116.374054 39.876251, 116.438599 39.832306)) |
| file:///root1/北京/北京分区/æœé˜³åŒº/æœé˜³åŒº2005/J50G004039.tif | POLYGON((116.438599 39.832306, 116.374054 39.832306, 116.438599 39.876251, 116.374054 39.876251, 116.438599 39.832306)) |
| file:///root1/北京/北京分区/æœé˜³åŒº/æœé˜³åŒº2003/J50G004039.tif | POLYGON((116.438599 39.832306, 116.374054 39.832306, 116.438599 39.876251, 116.374054 39.876251, 116.438599 39.832306)) |
| file:///root1/北京/北京分幅/J50G004039.tif | POLYGON((116.438599 39.832306, 116.374054 39.832306, 116.438599 39.876251, 116.374054 39.876251, 116.438599 39.832306)) |
+------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------+
4 rows in set