在SQL Server 2008上优化7000万个极高密度空间点云的最近邻查询

2023-12-02

我的 SQL Server 2008 R2 Express 数据库中有大约 7500 万条记录。每个都是对应于某个值的经纬度。该表有地理列。我正在尝试为给定的纬度经度(点)找到一个最近的邻居。我已经有一个带有空间索引的查询。但根据记录在数据库中的位置(例如第一季度或上季度),查询可能需要大约 3 到 30 秒才能找到最近的邻居。我觉得可以通过优化查询或空间索引来优化它以提供更快的结果。 现在应用了一些具有默认设置的空间索引。这是我的表和查询的样子。

CREATE TABLE lidar(
    [id] [bigint] IDENTITY(1,1) NOT NULL,
    [POINTID] [int] NOT NULL,
    [GRID_CODE] [numeric](17, 8) NULL,
    [geom] [geography] NULL,
 CONSTRAINT [PK_lidar_1] PRIMARY KEY CLUSTERED ([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]

我正在使用的空间索引:

CREATE SPATIAL INDEX [SPATIAL_lidar] ON [dbo].[lidar] ([geom]) USING  GEOGRAPHY_GRID 
WITH (
GRIDS =(LEVEL_1 = MEDIUM,LEVEL_2 = MEDIUM,LEVEL_3 = MEDIUM,LEVEL_4 = MEDIUM), 
CELLS_PER_OBJECT = 16, PAD_INDEX  = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF,  
ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]

这是我正在使用的查询:

declare @ms_at geography = 'POINT (-95.66 30.04)';
select TOP(1) nearPoints.geom.STAsText()as latlon 
from
(
select r.geom
from lidar r With(Index(SPATIAL_lidar))
where r.geom.STIntersects(@ms_at.STBuffer(1000)) = 1
) nearPoints

这是我的数据库中经纬度的示例。给出准确度和密度的概念。 7000万条记录全部针对一个城市(激光雷达数据)

POINT (-95.669434934023087 30.049513838913736)

现在这个查询给了我如上所述的结果,但我想尽可能地提高性能。我的猜测是,通过调整空间索引的默认值,我也许能够提高性能。这有什么线索吗?

我尝试将缓冲区从 10 更改为 1000,但结果几乎相同。

也欢迎任何其他提高性能的建议。

这是我现在正在使用的系统:

Windows 7 64bit Professional
Intel(R) Core(TM)2 Quad CPU    Q9650  @ 3.00GHz (4 CPUs), ~3.0GHz
Ram: 8 GB
NVIDIA GeForce 9500 GT

抱歉,这不是 SQL 答案,而是一种在数据受到某些约束的情况下获得可预测性能的方法。

数据多久更改一次?如果可能的话,您能否预先计算每个实体 5 个最近邻居的图表,并使用它来加快您的选择速度。

如果这些数据大部分是只读的,那么......

这些点分布的均匀程度如何?如果分布相当均匀且众所周知,那么您可以通过将每个坐标和索引存储在哈希表中来滚动自己的空间映射。

如果不需要数据库中的数据,请将其移出到内存映射文件以进行快速哈希查找。 (70m 记录应该可以轻松放入内存)。

我使用这种架构来生成亚毫秒级的查找,以显示广告和搜索引擎相关性。

==详细阐述==

您只需创建一个固定大小的正方形网格(如棋盘),然后将每个点映射到网格中,然后创建属于每个网格框的对象列表 - 如果您调整每个网格框的大小如果盒子正确的话,每个方格平均应该有 5-50 个点——原则上这是一个四叉树,但为了简单起见没有树。

对于将所有数据分散到存储桶中后为空的存储桶,您添加哪些最近的存储桶包含数据的信息。

现在,您可以从左到右对每个存储桶进行编号,以便每个存储桶都有一个可以根据坐标计算出的唯一编号 - 并且将每个存储桶插入到哈希表中,或者如果空间允许的话,就像直接查找表。

现在,当您进行查询时,您只需计算将映射到哪个存储桶,您将获得该存储桶中的对象列表,或者您将获得一个“空”存储桶,其中包含指向具有内容的最近存储桶的指针。

这将为您提供您正在寻找的第一个对象候选列表,现在您只需遍历并查看哪个是最接近的。

在 99% 的情况下,就是这样——但如果你担心 (a) 下一个桶中是否有一些实际上更接近的候选人,那么只需检查周围的 8 个桶,看看是否可以在那里找到更近的。

如果您现在还想获取所有最接近的对象的列表,那么还可以为每个对象计算 5 个最近邻居的简单网络,因此您最终将得到像 A->{B,C,D 这样的数据结构,E,F},B->{A,D,G,H,I},C->{A,J,K,G,M}....

这将形成一个简单的网络,您现在可以使用以下变量来遍历它Dijkstra在这里获取与您最近的点相邻的所有点。

构建数据结构需要时间,但一旦完成,完成正确的查找并返回数据集可以在亚毫秒内完成(不包括任何 http 或离线通信)

希望这可以帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在SQL Server 2008上优化7000万个极高密度空间点云的最近邻查询 的相关文章

  • Android ArrayList 的 IndexOutOfBoundsException [重复]

    这个问题在这里已经有答案了 我遇到了一个非常烦人的问题 一些代码抛出 IndexOutOfBoundsException 我真的不明白为什么 logcat 指向以下代码的 addTimetableItem 我们将对此进行更多解释 if so
  • R:返回数据框中匹配的行数和列数

    emperor lt rbind cbind Augustus Tiberius cbind Caligula Claudius 如何返回包含序列 us 的所有单元格的行号和列号 即 1 1 1 2 2 2 我们可以使用grepl得到一个v
  • 将solr 1.4索引升级到solr 3.3?

    我有一个使用 apache solr 1 4 构建的现有索引 我想在 3 3 版本中使用这个现有索引 正如您所知 索引格式在 3 x 之后发生了变化 那么如何才能做到这一点呢 我已经使用 Luke 将现有索引 即 1 4 版本 导出为 XM
  • 创建数据库索引的最佳实践和“经验法则”有哪些?

    我有一个应用程序 它循环访问数据库表中的大量记录 并对该数据库中的记录执行大量 SQL 和 Net 操作 目前我在 PostgreSQL 上使用 Castle ActiveRecord 我在几个字段上添加了一些基本的 btree 索引 正如
  • 在 SQL Server 中实现一对零或一关系

    我正在使用 Entity Framework 4 1 数据库第一种方法 我使用过旧数据库 在我的 edmx 文件中 它根据旧数据库中的表创建实体类 有一个一对零或一某些实体之间的关联 尽管我探索了数据库表以及它们之间的关系 但我不知道如何一
  • 包括 Oracle 中的等效项

    在 SQL Server 中你可以这样写 create index indx on T1 A B INCLUDE C D E 有没有办法在 Oracle 中做同样的事情 Refs http msdn microsoft com en us
  • TSQL 多列唯一约束也允许多个 Null

    我目前正在做一些从 MS Access 到 SQL Server 的迁移 Access 允许唯一索引中存在多个 Null 而 SQL Server 不允许 我一直在通过删除 SQL Server 中的索引并添加筛选索引来处理迁移 CREAT
  • Pentaho CE 上的地图可视化

    我正在运行 Pentaho ce 5 3 我已经使用星型模式立方体对其进行了测试 并且工作正常 现在我想将 Postgis 中存储的维度 包括空间维度 的 mdx 查询可视化为地图 不知道是否可行 或者我应该为此添加任何插件吗 根据您想要可
  • 良好的安全实践和自动身份范围管理是否相互排斥?

    我正在尝试使用自动身份范围管理 http msdn microsoft com en us library ms152543 aspx sectionToggle1 但是 确保我的用户可以在具有标识列的表中插入记录的唯一方法是使它们db o
  • 如何使用 XQuery 将值列表从 XML 提取到行中?

    我有一个 XQuery 如下 DECLARE x XML SELECT x
  • 查找 SSIS 包上次修改/部署日期 - SQL Server

    我想通过执行 SQL 查询找到 SSIS 包的最后修改日期 例如 下面的查询按降序返回过程的最后修改日期 我期待对 SSIS 包进行同样类型的查询 可以从DB获取这些信息吗 select name create date modify da
  • SQL Server 代理服务的凭据无效

    想要改进这篇文章吗 提供此问题的详细答案 包括引用和解释为什么你的答案是正确的 不够详细的答案可能会被编辑或删除 我正在尝试以管理员身份在本地计算机上安装 SQL Server 2008 开发服务器 在安装过程中我收到此错误 知道如何解决它
  • SQL Server 中 SYSDATETIME 数据类型的准确性

    我已经在 SQL Server 2008 的存储过程中使用 SYSDATETIME 进行了一些测试 我设置了一个包含带有 IDENTITY 字段的 datetime2 7 的表 我了解这种数据类型的精度和准确度之间的差异 但是 在从此示例中
  • ERROR 188 (HY000): FTS 查询超出结果缓存限制 mysql

    我的表的文本列上有全文索引 约有 1100 万行 表结构 CREATE TABLE review id int 11 NOT NULL AUTO INCREMENT comments text COLLATE utf8mb4 unicode
  • 在 Microsoft Sql Server 2008R2 及更高版本上隐藏登录数据库 [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 请任何人协助隐藏 sql server 2008R2 或更高版本上的可用数据库 我有一个新的登录用户 已映射到特定数据库 使用特定登录用户登录时 我可
  • 单个 sql 查询可以处理 sql server 中的 null 或值日期范围

    使用 SQL Server 2008 我有一个存储过程 其中开始日期和结束日期作为日期范围的输入参数 寻找一个singlesql 查询 其中在 where 子句中有一个开始日期和结束日期 可以处理日期均为空或都有值的两种情况 我不想使用 I
  • 删除 DB 但不删除 *.mdf / *.ldf

    我正在尝试自动化分离和删除数据库的过程 通过 VBS objshell run 如果我手动使用 SSMS 分离和删除我可以将数据库文件复制到另一个位置 但是如果我使用 sqlcmd U sa P MyPassword S local Q A
  • 在调用存储过程 Sql Server 2008 时使用嵌套存储过程结果

    是否可以在另一个存储过程中使用一个存储过程的结果 I e CREATE PROCEDURE dbo Proc1 ID INT mfgID INT DealerID INT AS BEGIN DECLARE Proc1Result UserD
  • SQL:将现有列设置为 MySQL 中的主键

    我有一个包含 3 列的数据库 id name somethingelse 该表没有设置索引 我收到 未定义索引 在 phpmyadmin 中id 是一个 7 位字母数字值 每行都是唯一的 我想将 Drugid 设置为主键 索引 我不知道有没
  • Elasticsearch 关于“空索引”的查询

    在我的应用程序中 我使用了几个elasticsearch索引 它们在初始状态下不包含索引文档 我认为这可以称为 空 该文档的映射是正确且有效的 该应用程序还有一个包含实体的关系数据库 这些实体可能具有在 elasticsearch 中关联的

随机推荐