wil*_*ten 7 sql-server spatial nearest-neighbor geometry
我有一个性能不佳的现有数据库解决方案。我正在使用浮点数等使用传统表结构搜索多维数据。数据库包含约 1-2M 行。
经过一番搜索,我发现了 SQL Server 空间数据类型,您可以在其中定义基于 Point 或 MultiPoint 的几何图形,您可以在其中进行距离搜索。我认为这可能是一个解决方案,但我需要一些帮助才能朝着正确的方向开始。
我当前的表结构如下,其中每行包含 2 个(最终更多)XYZ 值:
| ID | X1 | Y1 | Z1 | X2 | Y2 | Z2 |
| 1 | 1.1 | 2.2 | 5.1 | 1.2 | 2.1 | 4.1 |
| 2 | 3.2 | 5.1 | 4.1 | 3.2 | 3.1 | 3.1 |
| 3 | 4.1 | 2.3 | 6.3 | 4.2 | 4.1 | 2.1 |
| 4 | 2.4 | 3.5 | 2.1 | 3.2 | 2.1 | 4.1 |
Run Code Online (Sandbox Code Playgroud)
我在对每个 X、Y 和 Z 值进行容差搜索。
例如:
(pseudocode)
declare targetXYZ1 = (4.1, 2.2, 3.1);
declare targetXYZ2 = (2.8, 2.2, 4.2);
declare toleranceXYZ = (2,2,2)
Select ID from MyXYZTable tb
Where
Math.Abs(tb.X1 - targetXYZ1.X1) < toleranceXYZ.X
AND Math.Abs(tb.Y1 - targetXYZ1.Y1) < toleranceXYZ.Y
AND Math.Abs(tb.Z1 - targetXYZ1.Z1) < toleranceXYZ.Z
AND Math.Abs(tb.X2 - targetXYZ1.X2) < toleranceXYZ.X
AND Math.Abs(tb.Y2 - targetXYZ1.Y2) < toleranceXYZ.Y
AND Math.Abs(tb.Z2 - targetXYZ1.Z2) < toleranceXYZ.Z
Run Code Online (Sandbox Code Playgroud)
经过一些分析后,我可能需要为 xyz1 和 xyz2 制作一个包含 1 或 2 个几何列的表格,其中 geometry::Point(0, 0, 0)
我的问题:
非常欢迎任何建议或提示和技巧!
可能有一些空间方法在某种程度上有用,但您最大的问题将是 Z 值:
Z 坐标不用于库进行的任何计算,也不通过任何库计算进行。
这是设计使然。不要将 SQL 空间对象视为“真正的” 3D 几何对象,而是将它们视为带有“海拔标记”的地图坐标,不会被考虑到任何计算中。因此距离函数STDistance()
非常适用于“地图距离”,但不适用于真正的 3D 距离。
您可以定义一个点的 Z 值(和“M”值),但它不用于任何计算。
展示:
DECLARE @a geometry = geometry::Parse('POINT(0 0 0 2)');
DECLARE @b geometry = geometry::Parse('POINT(1 0 5 1)');
SELECT @a.Z, @b.Z, @a.STDistance(@b)
Run Code Online (Sandbox Code Playgroud)
将返回值
0 5 1
Run Code Online (Sandbox Code Playgroud)
显然,如果正确使用 Z,这两个点之间的距离应该大于 1。因此,它们可能不会像您希望的那样工作。
但是,如果您可以忽略 Z 值,那么执行这些计算将非常简单。您可以从现有表中读取这些值,如下所示:
SELECT geometry::Point(X1,Y1,0).STDistance(geometry::Point(X2,Y2,0))
From myTable;
Run Code Online (Sandbox Code Playgroud)
(0
在这种用法中,它不是Z 值,而是SRID。)
或者,如果您花时间更改它们的实际存储方式:
CREATE TABLE myPoints (ID INT, P1 geometry, P2 geometry)
INSERT myPoints
SELECT 1, geometry::Point(X1, Y1, 0), geometry::Point(X2, Y2, 0)
FROM oldTable
SELECT ID, P1.STDistance(P2)
FROM myPoints
Run Code Online (Sandbox Code Playgroud)
在我这里的一个较旧的答案中有一些相关的讨论。
编辑:一些进一步的想法:
geometry
对象将如何在性能方面与您手动进行数学比较。我想即时转换为 Geometry 对象会有一定程度的开销,但也许转换原始数据的存储方式会更好。测试将是这里的关键。STDistance()
功能,但很明显,你可以手动查询 Z
,并用它做的是数学自己的一部分,只是使用毕达哥拉斯:True3D_Distance ^ 2 = STDistance ^ 2 +(AZ-BZ)^ 2WHERE PointA.STDistance(PointB) + ABS(PointA.Z-PointB.Z) < tolerance
或者也许WHERE PointA.STDistance(PointB) < tolerance AND ABS(PointA.Z-PointB.Z) < tolerance
归档时间: |
|
查看次数: |
327 次 |
最近记录: |