SQL Server:地理搜索性能 - 查询最近的商店

Tar*_*lah 5 sql-server indexing geography geo sqlperformance

我有一个性能查询最近的商店:

我们有一张表格,其中包含一个国家/地区约50,000条记录(商店/销售点位置).

每条记录都有location"地理"类型的列

[LOCATION_geo] [geography]
Run Code Online (Sandbox Code Playgroud)

同样为了性能,我使用这种语法在该位置列上创建了一个SPATIAL INDEX

CREATE SPATIAL INDEX [LOCATION_geoIndex] 
ON [dbo].[StoreLocations] ([LOCATION_geo])
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]
GO
Run Code Online (Sandbox Code Playgroud)

我有一个存储过程来返回用户当前位置最近的1000商店.

USE [CompanyDB]
GO
SET STATISTICS TIME ON;  
GO  
declare @point geography;
    set @point = geography::Point(49.2471855, -123.1078987, 4326);

    SELECT top (1000) [id]
          ,[Location_Name]
          ,[LOCATION_geo]from [MYDB].[dbo].[StoreLocations]
        where [LOCATION_geo].STDistance(@point) <= 10000
        ORDER BY [LOCATION_geo].STDistance(@point)
Run Code Online (Sandbox Code Playgroud)

问题是查询总是需要656毫秒到800毫秒.这对我们的网站来说是不可接受的,因为我们期待太多同步调用.

(1000行受影响)

SQL Server执行时间:CPU时间= 923 ms,已用时间= 1511 ms.

注意:大多数商店位于一些城市(约10个城市).

此外,我注意到Clustered Index Seek的成本> =总查询成本的45%.

所以我的问题是有没有更好的方法来提高该查询的性能?

小智 1

我建议在表中再添加一列名为 distance 的列,其中 distance 是 LOCATION_geo 距 P​​oint(0, 0, 0) 的距离。请参阅下面的示例插入语句:

   INSERT INTO [GWDB].[dbo].[StoreLocations]
          ([id]
          ,[Location_Name]
          ,[LOCATION_geo]
          ,[Distance])
    Values(@id
          ,@Location_Name
          ,@LOCATION_geo
          ,@LOCATION_geo..STDistance(Point(0, 0, 0))
Run Code Online (Sandbox Code Playgroud)

您还应该在新的列距离上创建索引并更改您的存储过程,如下所示:

USE [CompanyDB]
GO
SET STATISTICS TIME ON;  
GO  
declare @point geography;
declare @distance float;
    set @point = geography::Point(49.2471855, -123.1078987, 4326);
    set @distance = @point.STDistance(geography::Point(0, 0, 0);

    SELECT top (1000) [id]
          ,[Location_Name]
          ,[LOCATION_geo]from [GWDB].[dbo].[StoreLocations]
        where 
        distance < @distance AND
        [LOCATION_geo].STDistance(@point) <= 10000
        ORDER BY [LOCATION_geo].STDistance(@point)
Run Code Online (Sandbox Code Playgroud)