1. 程式人生 > >MySQL空間查詢(Geometry類)

MySQL空間查詢(Geometry類)

效能測試:

一、建立支援查詢的表

建立一個包含空間資料的名為points的表。

CREATE TABLE points(

longitude  DOUBLE,

latitude  DOUBLE,

point  POINT

);

這條命令建立一個名為points的表,包含一個longitude欄位,一個latitude欄位,一個point欄位。

二、向資料庫中匯入資料

因筆者已有一個包含經緯度的檔案log.csv。把log.csv匯入表log。

LOAD DATA INFILE 'C:\\log.csv' 
INTO TABLE log 
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' ESCAPED BY '"' 
LINES TERMINATED BY  '\n'; 

把表log中的資料匯入新表points中

INSERT INTO points(longitude, latitude)SELECT longitude, latitude FROM log;

三、根據表points中的longitude,latitude欄位得到point欄位

UPDATE points SET point = GeomFromText(CONCAT('POINT(',points.longitude,' ',points.latitude,')'));

報錯:Error Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column To disable safe mode, toggle the option in Preferences -> SQL Queries and reconnect.

先執行SET SQL_SAFE_UPDATES = 0;語句,然後執行上面語句。

四、從表中讀取資料

1、讀取表中的point欄位

SELECT  AsText(point)  FROM points;

以上語句的返回結果中的point會被轉換成GIS標準字串。實際上AsText函式僅僅是把資料庫內部儲存的幾何物件轉化為一個字串而已。

2、返回一系列point的X()(經度)小於10,並且Y()(緯度)小於10的點的集合

SELECT AsText(point)  FROM points WHERE  X(point) < 10 AND Y(point) < 10;

3、

四、測試效能

SELECT  AsText(point) FROM points WHERE X(point) <13000000 and Y(point) > 60000000;

duration/fetch    :  11.606sec/0.047sec

SELECT *  FROM points WHERE longitude < 13000000 and  latitude > 60000000;

duration/fetch     :  11.2941sec/0.281sec

五、如果沒有資料也不必擔心,下面幫你製造資料

1、建立新表

CREATE TABLE `points` (

  `name` varchar(20) NOT NULL DEFAULT '',

  `location` point NOT NULL,

  `description` varchar(200) DEFAULT NULL,

  PRIMARY KEY (`name`),

  SPATIAL KEY `sp_index` (`location`)

) ENGINE=MyISAM DEFAULT CHARSET=gbk;


2、寫函式

delimiter // -- 將SQL識別符號設為 '//' 


CREATE PROCEDURE fill_points(
IN size INT(10)
)


BEGIN
DECLARE i DOUBLE(10,1) DEFAULT size;
DECLARE lon FLOAT(7,4);
DECLARE lat FLOAT(6,4);
DECLARE position VARCHAR(100);
 


DELETE FROM Points;
 
WHILE i > 0 DO
SET lon = RAND() * 360 - 180;
SET lat = RAND() * 180 - 90;
 
SET position = CONCAT( 'POINT(', lon, ' ', lat, ')' );
 
INSERT INTO Points(name, location) VALUES ( CONCAT('name_', i), GeomFromText(position) );
 
SET i = i - 1;
END WHILE;


END

3、生成資料

CALL fill_points(1000000);

4、查詢區域內的點

SET @center = GeomFromText('POINT(10 10)');

SET @radius = 30;

SET @bbox = CONCAT('POLYGON((',

X(@center) - @radius, ' ', Y(@center) - @radius, ',',

X(@center) + @radius, ' ', Y(@center) - @radius, ',',

X(@center) + @radius, ' ', Y(@center) + @radius, ',',

X(@center) - @radius, ' ', Y(@center) + @radius, ',',

X(@center) - @radius, ' ', Y(@center) - @radius, '))'

);

[1]

SELECT name, AsText(location)

FROM Points

WHERE Intersects( location, GeomFromText(@bbox) )

AND SQRT(POW( ABS( X(location) - X(@center)), 2) + POW( ABS(Y(location) - Y(@center)), 2 )) < @radius; To Obtain a result ordered by distance from the center of the selection area:

[2]

SELECT name, AsText(location), SQRT(POW( ABS( X(location) - X(@center)), 2) + POW( ABS(Y(location) - Y(@center)), 2 )) AS distance

FROM Points

WHERE Intersects( location, GeomFromText(@bbox) )

AND SQRT(POW( ABS( X(location) - X(@center)), 2) + POW( ABS(Y(location) - Y(@center)), 2 )) < @radius

ORDER BY distance;