在SQL Server 2008上的7000万点云上优化最近邻居查询


16

我在SQL Server 2008 R2 Express数据库中有大约7500万条记录。每个都是对应某个值的纬度。该表具有“地理位置”列。我正在尝试为给定的经度(点)找到一个最近的邻居。我已经有一个具有空间索引的查询。但是根据记录在数据库中的位置(例如第一季度或最后一个季度),查询可能需要3到30秒才能找到最近的邻居。我认为可以通过优化查询或空间索引来优化此方法,以得到更快的结果。现在,使用默认设置应用了一些空间索引。这是我的表和查询的样子。

CREATE TABLE lidar(
    [id] [bigint] IDENTITY(1,1) NOT NULL,
    [POINTID] [int] NOT NULL,
    [GRID_CODE] [numeric](17, 8) NULL,
    [geom] [geography] NULL,
 CONSTRAINT [PK_lidar_1] PRIMARY KEY CLUSTERED ([id] ASC)
 WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, 
 ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

我正在使用的空间索引:

CREATE SPATIAL INDEX [SPATIAL_lidar] ON [dbo].[lidar] ([geom]) USING  GEOGRAPHY_GRID 
WITH (
GRIDS =(LEVEL_1 = MEDIUM,LEVEL_2 = MEDIUM,LEVEL_3 = MEDIUM,LEVEL_4 = MEDIUM), 
CELLS_PER_OBJECT = 16, PAD_INDEX  = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF,  
ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]

这是我正在使用的查询:

declare @ms_at geography = 'POINT (-95.66 30.04)';
select TOP(1) nearPoints.geom.STAsText()as latlon 
from
(
select r.geom
from lidar r With(Index(SPATIAL_lidar))
where r.geom.STIntersects(@ms_at.STBuffer(1000)) = 1
) nearPoints

这是我的数据库中的经纬度示例。给出精度和密度的概念。7000万条记录全部针对一个城市(激光雷达数据)。

POINT (-95.669434934023087 30.049513838913736)

现在,此查询为我提供了如上所述的结果,但我想尽可能提高性能。我的猜测是通过调整我可能会高于的空间索引的默认值来更好地优化性能。有什么线索吗?

我尝试将缓冲区从10更改为1000,但结果几乎相同。

也欢迎任何其他改进性能的建议。

这是我现在正在使用的系统:

Windows 7 64bit Professional
Intel(R) Core(TM)2 Quad CPU    Q9650  @ 3.00GHz (4 CPUs), ~3.0GHz
Ram: 8 GB
NVIDIA GeForce 9500 GT

1
这是激光雷达数据吗?如果是这样,请考虑添加lidar标签。
Kirk Kuykendall,

2
我不会说SQL Server,但从我的直觉上看,您的查询必须查找位于目标点1000米缓冲区内的所有点。这点在多边形的测试将是方式比接近测试,这是在您提供的解决方案的基础较慢前面的问题
ub

@whuber:我尝试了基于距离的查询和以分钟为单位的时间。高的方式。可能是我在某些地方出错。从多边形中的这些点开始,需要花费时间(以秒为单位)。即使将缓冲区从10更改为10000,对时间的影响也很小。
Shaunak 2011年

1
@Shaunak然后,基于距离的查询就有些问题了,因为从理论上讲,它们可以使用适当的索引(例如KD树)平均以微秒(或更优)和毫秒(最坏的情况)完成。您可能需要考虑改进它们,而不是寻找优化缓冲区中搜索的方法。
ub

这是网格数据吗?为什么不使用栅格?
马修·斯内普

Answers:


9

尝试运行sp_help_spatial_geography_index存储过程以获取有关如何使用空间索引的详细信息。您应该可以使用类似:

declare @ms_at geography = 'POINT (-95.66 30.04)'
set @ms_at = @ms_at.STBuffer(1000).STAsText()
exec sp_help_spatial_geography_index 'lidar', 'SPATIAL_lidar', 0, @ms_at;

将结果发布到您的问题中,看看是否有任何突出之处。每个项目的含义可以在这里找到

如果投影了坐标,则还可以对计算出的X,Y字段进行简单的非空间查询,并检查X <MinX和X> MaxX等。

通过投影坐标(在GEOMETRY类型字段中),还可以将空间索引限制在数据范围内,这可以大大提高性能。用您的数据范围替换世界范围:

CREATE SPATIAL INDEX [SPATIAL_lidar] ON [dbo].[lidar] ([geom]) USING  GEOMETRY_GRID 
WITH (
GRIDS =(LEVEL_1 = MEDIUM,LEVEL_2 = MEDIUM,LEVEL_3 = MEDIUM,LEVEL_4 = MEDIUM), 
CELLS_PER_OBJECT = 16, PAD_INDEX  = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF,  
ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON,
BOUNDING_BOX =(-90, -180, 90, 180),) ON [PRIMARY]

1
根据technet.microsoft.com/zh-cn/library/bb934196.aspx,BOUNDING_BOX只能用于GEOMETRY_GRID,而不能用于GEOGRAPHY_GRID
Kelso

1
更新的答案。由于可以设置BOUNDING_BOX,因此GEOMETRY类型应该快得多。
geographika


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.