空间索引概述

适用于:SQL ServerAzure SQL 数据库Azure SQL 托管实例Microsoft Fabric 中的 SQL 数据库

SQL Server 支持空间数据和空间索引。 “空间索引” 是一种扩展索引,允许你对空间列编制索引。 空间列是包含空间数据类型(如 geometrygeography)的数据的表列。

Tip

SQL Server Spatial Tools 是一个由微软赞助的开源工具集,用于配合 SQL Server 中的空间类型使用。 此项目提供了一组可供应用程序使用的可重用函数。 这些函数可能包括数据转换例程、新转换、聚合等。有关更多详细信息,请参阅 GitHub 中的 Microsoft/SQLServerSpatialTools

关于空间索引

将索引空间分解成网格层次结构

在 SQL Server 中,空间索引使用 B 树构建而成,也就是说,这些索引必须按 B 树的线性顺序表示二维空间数据。 因此,将数据读入空间索引之前,SQL Server 先实现对空间的分层均匀分解。 索引创建过程会将空间分解成一个四级网格层次结构。 这些级别指的是第 1 级(顶级)、第 2 级、第 3 级和第 4 级。

每个后续级别都会进一步分解其上一级,因此上一级别的每个单元都包含下一级别的整个网格。 在给定级别上,所有网格沿两个轴都有相同数目的单元(例如 4x4 或 8x8),并且单元的大小都相同。

下图展示了在网格层次结构的每一层级中,右上角单元如何被分解为 4x4 网格。 实际上,所有单元都是这样拆分的。 因此,以此为例,将一个空间分解成四个级别的 4x4 网格实际上会总共产生 65,536 个第四级单元。

递归分割的四个级别

Note

用于空间索引的空间划分与应用程序数据所使用的计量单位无关。

网格层次结构单元格采用希尔伯特空间填充曲线的变体进行线性编号。 然而,出于演示目的,这里使用的是简单的按行编号,而不是由 Hilbert 曲线实际产生的编号。 在下图中,几个表示建筑物的多边形和表示街道的线已经放进了一个 4x4 的 1 级网格中。 第 1 级单元的编号为 1 到 16,编号从左上角的单元开始。

放置在 4x4 一级网格中的多边形和线段

网格密度

沿网格轴的单元数目确定了网格的 “密度”:单元数目越大,网格的密度越大。 例如,8x8 网格(产生 64 个单元)的密度就大于 4x4 网格(产生 16 个单元)的密度。 网格密度是以每个级别为基础定义的。

CREATE SPATIAL INDEXTransact-SQL 语句支持 GRIDS 子句,该子句允许在不同的级别指定不同的网格密度。 可以使用下列关键字之一指定给定级别的网格密度。

Keyword 网格配置 单元数目
LOW 4X4 16
MEDIUM 8X8 64
HIGH 16X16 256

在 SQL Server 中,当数据库兼容性级别设置为 100 或更低时,则在所有级别上默认值为 MEDIUM。 当数据库兼容级别设置为 110 或更高时,默认值为自动网格方案。 (自动网格表示 HLLLLLLL 的 8 级配置。)除了调整索引网格密度外,您还可以通过提示来调整每个对象的单元格数以及查询窗口中每个对象的单元格数。

你可以通过指定非默认的网格密度控制分解过程。 例如,在不同级别指定不同网格密度对于基于索引空间的大小和空间列中的对象来优化索引可能非常有用。

Note

当数据库兼容级别设置为 100 或更低时,空间索引的网格密度显示在 sys.spatial_index_tessellations 目录视图的 level_1_grid、level_2_grid、level_3_grid 和 level_4_grid 列中。 GEOMETRY_AUTO_GRID/GEOGRAPHY_AUTO_GRID 分割方案选项不会填充这些列。 使用自动网格选项时,sys.spatial_index_tessellations 目录视图对这些列使用 NULL 值。

Tessellation

将索引空间分解成网格层次结构后,空间索引将逐行读取空间列中的数据。 读取空间对象(或实例)的数据后,空间索引将为该对象执行 分割过程。 镶嵌过程通过将对象与其接触的一组网格单元关联起来,将该对象纳入网格层次结构中(接触单元)。 从网格层次结构的第 1 级开始,镶嵌过程将以广度优先的方式横向遍历该级别。 理论上,该过程可以继续逐级进行,直至完成全部四个级别。

镶嵌过程的输出是一组被触及的单元格,这些单元格会被记录在对象的空间索引中。 通过引用这些已记录单元,空间索引可以确定该对象在空间中相对于空间列中也存储在索引中的其他对象的位置。

镶嵌规则

为了限制为某个对象记录的被触及单元格数量,镶嵌过程会应用若干镶嵌规则。 这些规则决定了镶嵌过程的深度,以及哪些被触及的单元格会被记录到索引中。

这些规则如下:

  • 覆盖规则

    如果一个对象完全盖住了某个单元,则称该单元由该对象所“覆盖” 。 被覆盖的单元格会被计数,且不再进行镶嵌。 此规则应用于网格层次结构的所有级别。 覆盖规则简化了分割过程,并减少了空间索引记录的数据量。

  • 每对象单元数规则

    此规则强制执行每个对象的单元数限制,该限制确定每个对象可以具有的最大单元数(级别 1 例外)。 在较低层级,每对象单元数规则决定了可记录的关于该对象的信息量。

  • 最深层单元格规则

    最深单元规则通过只记录已为对象分割的最底部单元来生成该对象的最近似对象。 父单元不计入每对象单元数,这些单元不记录在索引中。

这些细分规则会在每一层网格上递归应用。 本节的其余部分将更详细地描述这些镶嵌规则。

覆盖规则

如果一个对象完全盖住了某个单元,则称该单元由该对象所“覆盖” 。 例如,在下图中,一个第 2 级单元 15.11 完全由八边形的中间部分所覆盖。

表面优化

被遮挡的单元格会被计数并记录在索引中,且该单元格不会进行进一步的细分。

每个对象单元格规则

每个对象的细分范围主要取决于空间索引的每个对象的单元格上限。 该上限定义了细分过程对每个对象可计数的最大单元格数量。 然而,请注意,每对象单元数规则不对第 1 级强制执行,因此可能超出此限制。 如果第 1 级计数达到或超过了“每个对象的单元格上限”,则较低级别将不再进行细分。

只要计数值小于“每个对象的单元格数限制”,划分过程就会继续。 从编号最低的接触单元(例如上图中的单元 15.6)开始,此过程将测试每个单元以评估是对其进行计数还是进行分割。 如果分割某单元将超出每对象单元数限制,将对该单元进行计数而不进行分割。 否则,该单元格将被划分,并且会统计该对象所触及的低级别单元格。 划分过程以此方式沿该层水平方向继续进行。 该过程会对镶嵌单元中较低层级的网格递归地重复进行,直到达到上限或没有更多单元可计数为止。

例如,考虑前面的插图,其中显示了一个完全嵌入一级网格第 15 个单元格的八边形。 在此图中,单元 15 已进行分割,将八边形分成了九个二级单元。 此图假定每对象单元数限制为 9 或更大。 然而,如果每对象单元数限制为 8 或更小,则单元 15 将不进行分割,而只为该对象对单元 15 进行计数。

默认情况下,每对象单元数限制为每个对象 16 个单元,这将在大多数空间索引的空间和精度之间提供一个令人满意的折中方案。 但是, CREATE SPATIAL INDEXTransact-SQL 语句支持一个 CELLS_PER_OBJECT =n 子句,该子句允许指定 1 到 8192 之间的每对象单元格限制(含 1 到 8192)。

Note

空间索引的 cells_per_object 设置显示在 sys.spatial_index_tessellations 目录视图中。

最深单元格规则

最深单元规则利用每个较低级别单元属于其上级单元这一事实:第 4 级单元属于第 3 级单元,第 3 级单元属于第 2 级单元,第 2 级单元属于第 1 级单元。 例如,属于单元 1.1.1.1 的对象也属于单元 1.1.1、1.1 和 1。 这种单元层次结构关系的知识内置到查询处理器。 因此,只有最深级别的单元需要记录在索引中,从而最大限度地减少了索引需要存储的信息。

在下图中,相对较小的菱形多边形被分割。 索引使用默认的每对象单元数限制 16,此对象较小,未达到该限制。 因此,细分将一直进行到第 4 层。 此多边形驻留在以下的第 1 级到第 3 级的单元中:4、4.4 以及 4.4.10 和 4.4.14。 但是,根据最深单元格规则,细分仅统计 12 个第 4 层单元格:4.4.10.13-15、4.4.14.1-3、4.4.14.5-7 以及 4.4.14.9-11。

最深单元优化

镶嵌方案

空间索引的行为部分取决于“分割方案” 。 该细分方案与数据类型相关。 在 SQL Server 中,空间索引支持两种分割方案:

  • 几何网格细分,即用于 geometry 数据类型的方案。

  • 地理网格细分,适用于地理位置数据类型的列。

Note

空间索引的 tessellation_scheme 设置显示在 sys.spatial_index_tessellations 目录视图中。

几何网格细分方案

GEOMETRY_AUTO_GRID 网格划分是 SQL Server 2012 (11.x) 及更高版本中 geometry 数据类型的默认网格划分方案。 GEOMETRY_GRID 分割是 SQL Server 2008 (10.0.x) 中 geometry 数据类型的唯一可用分割方案。 本节讨论了与使用空间索引时相关的几何网格细分方面,包括支持的方法和边界框。

Note

您可以通过 CREATE SPATIAL INDEX Transact-SQL 语句中的 USING (GEOMETRY_AUTO_GRID/GEOMETRY_GRID) 子句显式指定此细分方案。

边界框

几何图形数据占有的平面可以是无限的。 然而,在 SQL Server 中,空间索引需要有限空间。 为了建立有限空间以用于分解,几何图形网格分割方案需要矩形“边界框” 。 该边界框由四个坐标定义:(x-min,y-min)(x-max,y-max),这些坐标作为空间索引的属性存储。 这些坐标所表示的意义如下:

  • x-min 是边界框左下角的 x 坐标。

  • y-min 是左下角的 y 坐标。

  • x-max 是右上角的 x 坐标。

  • y-max 是右上角的 y 坐标。

Note

这些坐标由Transact-SQL 语句的 CREATE SPATIAL INDEX BOUNDING_BOX 子句指定。

(x-min,y-min) 以及 (x-max,y-max) 坐标确定边界框的位置和尺寸。 边界框的外部空间视作一个编号为 0 的单元。

空间索引将边界框内的空间进行分解。 网格层次结构中的第 1 级网格填满了边界框。 若要在网格层次结构中放置几何对象,空间索引会将该对象的坐标与边界框的坐标进行比较。

下图显示了由边界框的 (x-min,y-min)(x-max,y-max) 坐标定义的点。 网格层级结构的顶层显示为一个 4x4 网格。 出于演示的目的,这里省略了较低级别。 边界框的外部空间用零 (0) 指示。 请注意,对象“A”部分超出了边界框,对象“B”完全位于边界框外部,即单元 0 中。

显示坐标和单元 0 的边界框。

边界框对应于应用程序空间数据的某一部分。 索引的边界框是完全包含存储在空间列中的数据还是只包含其中部分数据取决于应用程序。 只有针对完全位于边界框内部的对象的计算操作才会受益于空间索引。 因此,要充分利用地理位置列上的空间索引,您需要指定一个包含所有或大部分对象的边界框。

Note

空间索引的网格密度可在 sys.spatial_index_tessellations 目录视图的 bounding_box_xmin、bounding_box_ymin、bounding_box_xmax 和 bounding_box_ymax 列中查看。

地理网格分割方案

此细分方案仅适用于地理位置列。 此部分总结了地理网格分割支持的方法,并讨论了如何将测量空间投影到平面上,该平面随后将分解成网格层次结构。

Note

您可以通过在 CREATE SPATIAL INDEXTransact-SQL 语句中使用 USING (GEOGRAPHY_AUTO_GRID/GEOGRAPHY_GRID) 子句来显式指定此细分方案。

将测量空间投影到平面上

geography 实例(对象)的计算将包含对象的空间视为测量椭圆体。 若要分解此空间,地理网格分割方案将椭圆体表面分为上半球和下半球,然后执行下列步骤:

  1. 将每个半球投影在四边形棱锥图面上。

  2. 将两个金字塔展平。

  3. 将展平后的棱锥连接起来,形成一个非欧几里得平面。

下图显示了此三步分解过程的示意图。 在棱锥图中,虚线表示每个棱锥图的四个面的边界。 步骤 1 和 2 显示测量椭圆体,使用一条绿色水平线表示赤道纬线,使用一系列绿色垂直线表示若干条经线。 步骤 1 展示了金字塔在两个半球上的投影。 步骤 2 显示了棱锥被压平的过程。 步骤 3 展示了展开后的棱锥在组合成一个平面后的样子,并显示了多条投影经线。 请注意,这些投影线伸直后长度不一,具体取决于它们落在棱锥图上的位置。

椭圆体在平面上的投影

空间投影到平面上之后,此平面将会分解成四级网格层次结构。 不同级别可以使用不同的网格密度。 下图显示了该平面被分解为 4x4 的第 1 级网格后的状态。 出于演示目的,这里省略了网格层次结构的较低级别。 事实上,此平面完全分解成了一个四级网格层次结构。 分解过程完成后,系统将按行从 geography 列读取地理数据,并依次对每个对象执行细分操作。

第 1 级地理网格

空间索引支持的方法

空间索引支持的几何图形方法

空间索引在特定条件下支持以下基于集合的几何方法:STContains()、STDistance()、STEquals()、STIntersects()、STOverlaps()、STTouches() 和 STWithin()。 若要让这些方法得到空间索引的支持,它们必须在查询的 WHERE 子句或 JOIN ON 子句中使用,并且必须出现在具有以下一般形式的谓词中:

geometry1.method_name(geometry2)comparison_operator**valid_number

若要返回非 NULL 结果, geometry1geometry2 必须具有相同的 空间引用标识符 (SRID)。 否则,该方法将返回 NULL。

空间索引支持以下谓词形式:

空间索引支持的地域方法

在某些条件下,空间索引支持以下面向集合的地理方法:STIntersects()、STEquals() 和 STDistance()。 若要使空间索引支持这些方法,必须在查询的 WHERE 子句中使用这些方法,并且必须在采用如下常规形式的谓词中执行这些方法。

geography1.method_name(geography2)comparison_operator**valid_number

若要返回非 NULL 结果, geography1geography2 必须具有相同的 空间引用标识符 (SRID)。 否则,该方法将返回 NULL。

空间索引支持以下谓词形式:

使用空间索引的查询

WHERE 子句中包含索引空间运算符的查询支持空间索引。 示例语法如下:

[spatial object].SpatialMethod([reference spatial object]) [ = | < ] [const literal or variable]  

查询优化器可理解空间操作的交换性(即 @a.STIntersects(@b) = @b.STIntersects(@a) )。 但是,如果比较的开头不包含空间运算符,将不会使用空间索引(例如, WHERE 1 = spatial op 将不会使用空间索引)。 要使用空间索引,请重写比较(例如 WHERE spatial op = 1)。

与任何其他索引一样,在支持使用空间索引时,系统将根据开销选择是否使用空间索引,因此,即使使用空间索引的所有要求都得到满足,查询优化器也可能不选用空间索引。 可使用显示计划查看是否使用了空间索引,在必要时,可提供查询提示以强制使用所需的查询计划。

邻近点查询类型也支持空间索引,但必须要编写特定的查询语法。 正确的语法为:

SELECT TOP(K) [WITH TIES] *   
FROM <Table> AS T [WITH(INDEX(<SpatialIndex>))]  
WHERE <SpatialColumn>.STDistance(@reference_object) IS NOT NULL  
ORDER BY <SpatialColumn>.STDistance(@reference_object) [;]  

另请参阅

空间数据 (SQL Server)