将非空间表与非空间列上的空间表连接时提高查询响应速度

wxd*_*dan 3 sql-server execution-plan spatial sql-server-2014 query-performance

我有一个经常更新影响某些几何图形的事件的表。几何区域是固定的,但可能有一个事件同时影响多个区域,因此两者之间存在多对多的关系。单个区域也可能同时受到多个事件的影响。

例如:

事件ID 区域编号
1 15
1 31
2 46
3 46
3 55
4 15

这些区域在我的表中表示为 ID 值。我需要在空间上表示这些值,因此我需要将这些值连接到包含s 和几何图形的event_id and area_id查找表。area_id不幸的是,这些表位于同一 SQL Server 2014 实例上的两个独立数据库中。

问题是这个连接过程非常慢;返回 18k-24k 行需要 90 秒到 3 分钟不等,具体取决于当前有多少事件处于活动状态。几何查找表包含 84k 行。

事件表结构(为了简单起见,删除了一些附加列):

USE Events_DB;
CREATE TABLE [dbo].[Events](
    [EVENTS_ID] [bigint] NOT NULL,
    [AREA_ID] [bigint] NOT NULL,
    [START_DATE_TIME] [smalldatetime] NULL,
    [END_DATE_TIME] [smalldatetime] NULL,
 CONSTRAINT [PK_Events] PRIMARY KEY CLUSTERED 
(
    [EVENTS_ID] ASC,
    [AREA_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)

几何查找表结构:

USE Geom_DB;
CREATE TABLE [dbo].[Area_Geom](
    [AREA_ID] [int] NOT NULL,
    [Geom] [geometry] NOT NULL,
 CONSTRAINT [Area_Geom] PRIMARY KEY CLUSTERED 
(
    [AREA_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)

我的查询如下。我对事件和区域 ID 使用 CTE,因为它们在完整查询的其他地方使用,但我已将瓶颈缩小到该特定部分。

WITH active_ids (EVENTS_ID, AREA_ID) AS (SELECT DISTINCT EVENTS_ID, AREA_ID
        FROM EVENTS
        WHERE END_DATE_TIME > getUTCdate())

SELECT geom FROM Area_Geom WHERE area_id IN (SELECT area_id FROM active_ids);
Run Code Online (Sandbox Code Playgroud)

执行计划显示Area_Geom表上主键索引的聚集索引扫描;扫描该表中存储的约 84k 行需要花费近 2 分钟的时间。

我向我们公司的一位 DBA 提出了这个问题,他被难住了。我可以采取其他措施来提高性能吗?我知道连接的跨数据库部分是问题的一部分,不幸的是,我对此无能为力。

我确实注意到两个表上的两个Area_ID值有两种不同的类型(bigint 和 int);然而,将 CTE 中的 Area_ID 转换为 int 对性能几乎没有影响。

Eri*_*ing 6

\xe2\x9b\x88\xef\xb8\x8f\xe2\x9b\x88\xef\xb8\x8f\xe2\x9b\x88\xef\xb8\x8f

\n

好消息!您的查询很快就完成了!

\n

坚果

\n

坏消息!需要很长时间才能去做其他事情

\n

坚果

\n

考虑到与 CPU 相比,这里的运行时间很长,您可以打赌查询要么被阻止,要么接收结果花了很长时间。

\n

如果您运行相同的查询并将其转储到 #temp 表中,这样就不会将结果返回到 SSMS,这应该有助于确定瓶颈是在服务器端还是客户端。

\n
WITH \n    active_ids AS \n(\n    SELECT DISTINCT \n        e.AREA_ID\n    FROM [EVENTS] AS e\n    WHERE END_DATE_TIME > GETUTCDATE()\n)\nSELECT\n    a.*\nINTO #active_ids\nFROM active_ids AS a;\n\nSELECT \n    a.geom \nINTO #Area_Geom\nFROM Area_Geom AS a\nWHERE area_id IN (SELECT ai.area_id FROM #active_ids AS ai);\n\nSELECT\n    ag.*\nFROM #Area_Geom AS ag;\n
Run Code Online (Sandbox Code Playgroud)\n