超过 9900 万条记录带有地理列和空间索引 - 查询非常非常慢!

Wil*_*vis 6 index sql-server spatial

我使用 SQL Server 已经很长时间了,但直到最近才遇到处理空间数据的需要。我进入了一个大量使用它的环境,我的第一个真正挑战是让查询更快地运行(并停止超时),以针对具有地理数据类型列(和索引)的表。

我们使用一个查询来标识该表中在多边形和多多边形中找到的所有地理点。这个表中有超过 9900 万条记录,我不知道如何调整这个野兽的性能!我已经确定聚集索引比需要的大一点,并打算添加一个标识列来做两件事:1) 减小聚集索引的大小。2) 消除插入的页面拆分。虽然我希望从这样做中得到一些缓解,但我并不乐观它会对空间查询有很大帮助。

鉴于我几乎完全缺乏空间数据的知识/经验,我无法做得更好。

Example query:

    Declare @OrgID int
    Declare @Geog geography

    Set @OrgID =100011

    /* This will return a multi polygon */
    SELECT @Geog = geog 
    FROM Organization
    WHERE orgid= @orgid

    Select count(*)
    FROM ProblemChild WITH (INDEX(IDX_geog))  
    WHERE Geog.STIntersects(@geog) = 1) 

    Table Design:
    CREATE TABLE [dbo].[ProblemChild](
        [Phone] [char](10) NOT NULL,
        [Lat] [float] NOT NULL,
        [Lon] [float] NOT NULL,
        [Geog] [geography] NOT NULL,
        [Recordsource] [varchar](2) NOT NULL
     CONSTRAINT [PK_Phone] PRIMARY KEY CLUSTERED 
    ([Phone] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY]
    ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
    GO

Index design:

    CREATE SPATIAL INDEX [IDX_geog] ON [dbo].[[ProblemChild]]
    ([Geog]
    )USING  GEOGRAPHY_GRID 
    WITH (GRIDS =(LEVEL_1 = HIGH,LEVEL_2 = HIGH,LEVEL_3 = HIGH,LEVEL_4 = MEDIUM), 
    CELLS_PER_OBJECT = 20, PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    GO

With:

    Number of records:  99,155,267

    MinLat      MinLon      MaxLat      MaxLon
    18.957356   -166.512394 71.292528   -66.967883
Run Code Online (Sandbox Code Playgroud)

Rob*_*ley 4

查看估计的查询计划,并确保正在使用索引。

此外,多多边形的复杂性可能是一个重要因素。如果您将索引想象为 MultiPolygon 上的一系列网格,则将存在完全被 MultiPolygon 覆盖或完全不被 MultiPolygon 覆盖的网格。您的 ProblemChild 点落入这些网格中很容易。当网格仅被 MultiPolygon 部分覆盖时,它将深入到下一个级别并尝试相同的操作。

当没有更多的网格级别可供钻取时,复杂性就会真正显现出来。如果您有一条特别有皱纹的线,并且您需要找出特定点位于该线的哪一侧,则需要检查大量线段并围绕这些进行数学计算。如果您可以大大简化 MultiPolygon,它将显着加快查询速度。您可以使用 .Reduce() 方法来完成此操作,但是您需要注意正确性,以防边界附近的点被简化后会位于线的另一侧。

我所说的简化是指减少它。想象一个八边形,有八个点。如果使用六个点或四点正方形来表达,则形状会变得不同,并且随着点数的减少,角附近的某些东西可能会向内或向外移动。

编辑:我已经在http://sqlblog.com/blogs/rob_farley/archive/2015/04/29/tuning-slow-spatial-queries-in-sql-server.aspx上发表了有关此主题的博客