seb*_*b49 12 performance sql-server sql-server-2012 spatial query-performance
表T_PIN
有 300,000 个引脚和T_POLYGON
36,000 个多边形。T_PIN
有这个索引:
CREATE SPATIAL INDEX [T_PIN_COORD] ON [dbo].[T_PIN]
(
[Coord]
)USING GEOGRAPHY_GRID
WITH (GRIDS =(LEVEL_1 = HIGH,LEVEL_2 = HIGH,LEVEL_3 = HIGH,LEVEL_4 = HIGH),
CELLS_PER_OBJECT = 128, 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];
Run Code Online (Sandbox Code Playgroud)
T_POLYGON
已:
CREATE SPATIAL INDEX [T_POLYGON_COORD] ON [dbo].[T_POLYGON]
(
[COORD]
)USING GEOGRAPHY_GRID
WITH (GRIDS =(LEVEL_1 = HIGH,LEVEL_2 = HIGH,LEVEL_3 = HIGH,LEVEL_4 = HIGH),
CELLS_PER_OBJECT = 128, 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];
Run Code Online (Sandbox Code Playgroud)
查询找到交集T_PIN
,并T_POLYGON
需要45分钟以上来执行:
SELECT COUNT(*)
FROM T_PIN
INNER JOIN T_POLYGON
ON T_PIN.Coord.STIntersects(T_POLYGON.COORD) = 1;
Run Code Online (Sandbox Code Playgroud)
结果是 4,438,318 行。
如何加速此查询?
首先,通过查看查询执行计划来检查是否正在使用空间索引,并查看是否有聚集索引查找(空间)项。
假设正在使用它,您可以尝试添加一个基于带有简化多边形的边界框的辅助/简化过滤器,以便首先检查。然后可以通过主过滤器运行与这些简化多边形的匹配以获得最终结果。
1) 在 [dbo].[T_POLYGON] 表中添加一个新的 geography 和 geometry 列:
ALTER TABLE [dbo].[T_POLYGON] ADD SimplePolysGeom geometry;
ALTER TABLE [dbo].[T_POLYGON] ADD SimplePolysGeog geography;
Run Code Online (Sandbox Code Playgroud)
2) 创建边界框多边形(这涉及到几何的初始转换以利用 STEnvelope()):
UPDATE [dbo].[T_POLYGON] SET SimplePolysGeom = geometry::STGeomFromWKB(
COORD.STAsBinary(), COORD.STSrid).STEnvelope();
UPDATE [dbo].[T_POLYGON] SET SimplePolysGeog = geography::STGeomFromWKB(
SimplePolysGeom.STAsBinary(), SimplePolysGeom.STSrid);
Run Code Online (Sandbox Code Playgroud)
3)在简化地理列上创建空间索引
4) 根据这个简化的地理列获取交集,然后再次过滤匹配的地理数据类型。大致是这样的:
;WITH cte AS
(
SELECT pinID, polygonID FROM T_PIN INNER JOIN T_POLYGON
ON T_PIN.Coord.STIntersects(T_POLYGON.SimplePolysGeog ) = 1
)
SELECT COUNT(*)
FROM T_PIN
INNER JOIN T_POLYGON
ON T_PIN.Coord.STIntersects(T_POLYGON.COORD) = 1
AND T_PIN.pinID IN (SELECT pinID FROM cte)
AND T_POLYGON.polygonID IN (SELECT polygonID FROM cte)
Run Code Online (Sandbox Code Playgroud)
编辑:您可以用这个计算的、持久的列替换 (1) 和 (2)。感谢保罗怀特的建议。
ALTER TABLE [dbo].[T_POLYGON] ADD SimplePolysGeog AS ([geography]::STGeomFromWKB([geometry]::STGeomFromWKB([COORD].[STAsBinary](),[COORD].[STSrid]).STEnvelope().STAsBinary(),(4326))) PERSISTED
Run Code Online (Sandbox Code Playgroud)
由于多边形的复杂性,此类查询通常需要很长时间。我见过复杂的海岸线(例如)需要很长时间才能测试靠近其边界的点,必须缩放许多级别才能确定某个点是在内部还是在外部。
...所以你可以尝试.Reduce()
'ing多边形,看看是否有帮助。
有关该功能的更多信息,请参阅http://msdn.microsoft.com/en-us/library/cc627410.aspx
归档时间: |
|
查看次数: |
6649 次 |
最近记录: |