我有一个带geometry
列的表。对于一条记录,只Point
存储一条。已创建空间索引,但搜索最近位置的查询不使用此索引,导致性能不佳。
示例脚本:
--Create the table
create table Location(
LocationID int not null identity(1,1) primary key,
LocationPoint geometry
)
--add records
declare @counter int =0
WHILE @counter<150000
BEGIN
set nocount on
--select
set @counter =@counter +1
declare @RandomLocation geometry=geometry::Point(RAND() *1000, RAND() *1000, 0)
insert into Location(LocationPoint) values (@RandomLocation)
END
--create index
CREATE SPATIAL INDEX SPATIAL_StructureBE ON dbo.Location(LocationPoint)
USING GEOMETRY_GRID WITH (
BOUNDING_BOX = (xmin = 0.0, ymin = 0.0, xmax = 1000, ymax = 1000),
GRIDS = ( LEVEL_1 = MEDIUM, LEVEL_2 = MEDIUM, LEVEL_3 = MEDIUM, LEVEL_4 = MEDIUM),
CELLS_PER_OBJECT = 16,
STATISTICS_NORECOMPUTE = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON)
--Search, this query should use the index but it doesn't
declare @CurrentLocation geometry=geometry::Point(24,50, 0)
select top 1 *
from Location
order by LocationPoint.STDistance(@CurrentLocation) asc
正确的。遗憾的是,在这种情况下,空间索引没有得到利用。
空间索引提供一组网格,允许系统识别与这些网格重叠的几何(或地理)。
您最好的选择是设置可接受的接近度阈值,并尝试使用 STBuffer 之类的东西。STIntersects 效果很好,如果没有找到,您可以增加此阈值(例如,如果没有找到,则使用第二个 OUTER APPLY。
编辑:他们现在做!检查我的帖子... http://blogs.lobsterpot.com.au/2014/08/14/sql-spatial-getting-nearest-calculations-working-properly/
总之,要使用您的索引,您需要确保您的 ORDER BY 值不能为 NULL - 只需添加一个 WHERE...IS NOT NULL 子句,它应该可以工作。
正如您在此处看到的:http ://technet.microsoft.com/en-us/library/bb895373%28v=sql.105%29.aspx ,不仅可以使用空间索引的方法数量有限,而且只能在 WHERE 或 JOIN ON 子句中使用。
您正在尝试在不支持使用索引的 ORDER BY 子句中使用 STDistance 方法。
编辑:
您可能会创建一个距离表,加入该表(因此 - 理论上 - 使用空间索引),然后对加入表的列进行排序。
某事... ... INNER JOIN [distances] ON LocationPoint.STDistance(@CurrentLocation)<[distances].[maxdistance] AND NOT(LocationPoint.STDistance(@CurrentLocation)<[distances].[mindistance])
(使用 2 列,所以你不一定要线性缩放)