在SQL Server 2012上使用STDistance和Spatial索引比使用COS,SIN& ACOS计算并给出椭圆形结果

时间:2015-08-25 13:30:21

标签: tsql geometry spatial geography

我在SQL Server 2012数据库中有一个包含3.000.000条记录的表。这些记录代表地图上的一个点。这些记录具有x,y坐标和地理点作为字段(x,y,geo)。 我需要计算距某一点10.000米范围内的所有点。

查询号码1我用:

DECLARE @point geography
DECLARE @rad float

SET @point = geography::STGeomFromText('POINT(51.2207099068778  4.39961050577564)', 4326);
SET @rad = 10000

SELECT count(1) 
FROM t_mailbox WITH (INDEX(SIndx_t_mailbox_geo_MHHM_512))
WHERE 
@point.STDistance(geo) <= @rad

结果:找到273.346分需要4秒钟。在地图上绘制这些点会在地图上生成椭圆形状。 确定这是错误的,因为并非所有点都包含在结果中。

查询号码2我用:

declare @radius int = 10000

DECLARE @x float = 51.2207099068778
DECLARE @y float = 4.39961050577564

SELECT count(1) 
FROM t_mailbox
WHERE 
ACOS(COS(RADIANS(90-@x))*COS(RADIANS(90-x)) +SIN(RADIANS(90-@x)) *SIN(RADIANS(90-x))*COS(RADIANS(@y-y)))*6371000 <= @radius

结果:找到564.547分需要2秒钟。在地图上绘制这些点可以得到一个完美的圆形。

问题:

  1. 为什么使用空间索引和STDistance比使用SIN,COS和ACOS的更复杂的查询慢?
  2. 为什么结果是错误的椭圆形点?
  3. 我做错了什么?

2 个答案:

答案 0 :(得分:1)

地球数据绘制在球体表面上。这意味着它看起来与几何(平面)数据不同。

想象一下,拿一个地球仪,并在其上画一点。然后拿一个指南针围绕该点画一个圆圈。现在将皮肤剥离地球。请注意,它不是平坦的,要使它平坦,你必须伸展它。现在大多数人这样做的方式是伸展顶部和底部(北极/南极)并拉伸它直到它与赤道相同的长度。这使得你画圆形的椭圆形水平方向比垂直方向更大。

现在,您使用的公式是平面内半径范围内的点。这意味着您假设两条经度线之间的距离无论您的纬度是多少(距离北极5英尺,90度和91度经度之间的距离远小于赤道)。

在墨卡托投影地图上,此公式将制作一个完美圆形的地图,但在地球上,它不是。希望这是有道理的。

关于速度问题:A:苹果到橘子,你正在做不同的计算。和B:在不知道如何设置索引的情况下,很难进行分析,但地理索引非常糟糕,无论在国家这样的大型地理位置上它的效果都更好。

答案 1 :(得分:0)

虽然 hcaelxxam 完美地回答了“为什么”,但可能通过离开STDistance()来获得更好的效果。虽然并非总是如此,但我一般认为最好使用STIntersects()STWithin()来实现距离 - 你如何做到这一点非常简单!

尝试将您的查询更改为以下内容。我对结果感兴趣:

DECLARE @point geography;
DECLARE @rad float = 10000;

SET @point = geography::STGeomFromText('POINT(51.2207099068778  4.39961050577564)', 4326).STBuffer(@rad); -- We're creating the "oval" here

SELECT count(1) 
FROM t_mailbox WITH (INDEX(SIndx_t_mailbox_geo_MHHM_512))
WHERE 
@point.STIntersects(geo) = 1

您可能还希望尝试使用和不使用索引提示。有时,强制它可能会生成低效的查询计划。