Entity Framework函数执行位置及EF6空间查询远程超时问题解析
Entity Framework中C#空间函数的执行位置及性能问题解析
核心问题解答
对于System.Data.Entity.Spatial中的Distance()这类EF内置空间函数,EF6会将其转换为对应的SQL Server空间函数(如STDistance)在数据库端执行,不会把全表数据拉取到本地再做计算。从你提供的转换后SQL也能验证这一点——逻辑完全在SQL层面实现,无本地计算痕迹。
性能差异原因排查
你的查询在本地MDF文件和远程SQL Server实例(同一份MDF)上性能差异巨大,核心原因在于:
- 本地MDF文件在EF6默认处理下,会被识别为高版本SQL Server环境,空间查询优化更充分;
- 远程使用的是SQL Server 2012,该版本对大规模空间数据的并行查询优化存在缺陷,导致
STDistance这类空间运算性能极差。
解决方案
- 升级SQL Server版本:更换为SQL Server 2019后,空间查询性能会和本地MDF环境一致,这是最优解。
- 旧版本修复:如果无法升级,可应用SQL Server 2012/2008 R2针对大规模空间数据并行查询慢问题的官方性能修复补丁。
附:查询代码与转换后的SQL
原始EF6 LINQ查询
List<Segments> CloseSel = _context?.Segments .Where(sv => listGeos.Any(geo => sv.Geometry_Data.Distance(geo) <= radius)) .ToList();
EF转换后的SQL查询
SELECT [Extent1].[Id_Segment] AS [Id_Segment], ... [Extent1].[Geometry_Data] AS [Geometry_Data] FROM [dbo].[Segments] AS [Extent1] WHERE EXISTS (SELECT 1 AS [C1] FROM (SELECT geometry::STGeomFromText(N'POINT (35 30)', 0) AS [C1] FROM ( SELECT 1 AS X ) AS [SingleRowTable1] UNION ALL SELECT geometry::STGeomFromText(N'POINT (45 20)', 0) AS [C1] FROM ( SELECT 1 AS X ) AS [SingleRowTable2] ... UNION ALL SELECT geometry::STGeomFromText(N'POINT (25 10)', 0) AS [C1] FROM ( SELECT 1 AS X ) AS [SingleRowTable13]) AS [UnionAll12] WHERE ([Extent1].[Geometry_Data].STDistance([UnionAll12].[C1])) <= 5 )
内容的提问来源于stack exchange,提问作者Corentin Salomon
相关产品推荐
相关产品推荐

