【发布时间】:2016-04-09 07:00:20
【问题描述】:
我正在与SQL server 2008 合作进行查询,该查询在距正在移动的中心点一定距离内查找用户 - 这意味着我经常访问数据库(新结果需要添加到现有集合中,而被删除),节省的每一毫秒都是有价值的。
我们正在使用以下查询的 ATM(使用 Id 是因为它们是索引 ATM 并且在尝试速度时很好):
declare @lat int = 500,
@lon int = 700
SELECT @lat, @lon, id, journeyid, ((ACOS(SIN(@lat * PI() / 180) * SIN([Id] * PI() / 180) +
COS(@lat * PI() / 180) * COS([Id] * PI() / 180) * COS((@lon - [JourneyId]) *
PI() / 180)) * 180 / PI()) * 60 * 1.1515) as dist
FROM [OnlineLegal_dev1].[dbo].[Customer]
group by [Id], [JourneyId], ((ACOS(SIN(@lat * PI() / 180) * SIN([Id] * PI() / 180) +
COS(@lat * PI() / 180) * COS([Id] * PI() / 180) * COS((@lon - [JourneyId]) *
PI() / 180)) * 180 / PI()) * 60 * 1.1515)
HAVING ((ACOS(SIN(@lat * PI() / 180) * SIN([Id] * PI() / 180) +
COS(@lat * PI() / 180) * COS([Id] * PI() / 180) * COS((@lon - [JourneyId]) *
PI() / 180)) * 180 / PI()) * 60 * 1.1515)<=10000
ORDER BY ((ACOS(SIN(@lat * PI() / 180) * SIN([Id] * PI() / 180) +
COS(@lat * PI() / 180) * COS([Id] * PI() / 180) * COS((@lon - [JourneyId]) *
PI() / 180)) * 180 / PI()) * 60 * 1.1515) ASC
当前选择前 1k 记录的速度是 00:00:00.097
我怎样才能进一步优化它以提高速度?
【问题讨论】:
-
你能解释一下你的公式吗(我猜是一些球面几何)?取身份证的窦看起来很奇怪。为什么不能用毕达哥拉斯简单计算距离?
-
@OlivierJacot-Descombes 使用 ID,因为这些列已编入索引,在实际应用程序中它将是纬度经度。它会弯曲以说明距离赤道更远的坐标的地球圆度。如果这不能很好地优化,我们可能使用的另一个选项是平方乘以国家/地区的常数,因为我们位于欧洲,这里的国家/地区很小。
-
有什么理由不在这里使用地理数据类型并让数学在 CLR 中完成?
-
@BenThul TBH 我从未使用过它,但我仍然很难相信它会比纯 sql 解决方案更快,我错过了什么吗?
-
是的,你是。 CLR 擅长(除其他外)像您正在做的计算繁重的事情。此外,您还可以利用 geography 类型的优势,而不是假设地球是一个完美的球体(就像您使用的 Haversine forumula 一样),而是一个扁球体。
标签: sql-server sql-server-2008 optimization query-optimization geospatial