【问题标题】:Big data with spatial queries/indexing具有空间查询/索引的大数据
【发布时间】:2015-08-21 17:22:12
【问题描述】:

目前我正在使用 SQL Server,但在扩展不相关的 1 亿条记录时遇到问题,每天执行大约 100 万次写入,32 GB 的内存已用完,CPU 大部分时间都在 80%-90%。这让我厌倦了使用 SQL Server,但如果可能的话,我想继续使用它。 我一直在研究 mongoDB。

我有一个新项目,它需要存储大约 1 亿条空间记录,全部为折线,并具有与几何相关的 15 个左右的属性。我知道 SQL Server 和 mongoDB 都支持空间索引,与 R-tree 索引相比,mongoDB 使用劣质(如我所读)Geohash。

我认为它们在 GIS 数据的性能方面取得了平衡,因为我觉得即使 mongoDB 的空间索引较差,但与 SQL Server 相比,它的读取速度的剪切性能将弥补这一点。

我遇到的真正问题是对于每条折线,都会有时间数据与每条折线相关联。这个数字从 20 到 2000 不等,具体取决于它可以扩展的程度。现在是 20 亿,并且有可能增长到 2000 亿。

折线数据不会超过1亿条,每条记录大约1KB(100GB)。如果我们将所有的数据都存储为非规范化的,并且不关心复制 GIS 数据以避免进行 JOIN,那就是 2-200 TB,我基本上无法管理。

因此,我认为需要进行一些非规范化,一个表/集合中的 GIS 数据和另一个表/集合中的关联时间数据。

很快,一个地图请求将进入并请求一个图块,该图块应查询该边界框的所有 GIS 信息(想想空间交叉点),并使用此结果,需要查询时间范围内的 timedata AVERAGE选定的多段线。数据集在到达地图渲染器时必须在一起(JOINED)。在平移地图时,所有这些都会每秒发生 12-20 次,因为地图会根据时间数据为折线着色。

我的问题是,考虑到 mongoDB 空间索引性能,使用 geoIntersects 时从 1 亿条记录到 250,000 条记录是否会成为问题?

然后,一旦找到 250,000 条折线,我将需要查询与某个 WHERE 子句的 250,000 条折线相关的时间的时间数据,很可能是一个时间范围。考虑到该表将包含超过 20 亿条记录,mongoDB 能否做到这一点,并且可以在亚秒内完成?

现在,我可以在 SQL Server 2012 中使用空间索引在大约 4 秒内从 200 万条折线增加到 200,000 条折线。这是可以接受的,但它根本没有考虑到时间数据,而且它的数据比实际数据少 50 倍。

我觉得使用 mongoDB 进行 JOIN 操作会破坏 mongoDB 的目的,并且不会产生比 SQL Server 更好的性能。

完成这项任务的数据库建议是什么?

要点:

  • 支持空间索引,以便正确查询 GIS 数据。

  • 数据只会每年写入一次,基本上是 100% 读取。

  • 大多数关于 timedata 的查询都需要一个时间范围内的 AVERAGE

  • 低负载,任何时候只有 2-10 个用户连接

服务器/服务器的预算约为每月 1000 美元。

编辑:

时间数据包含每 15 分钟在该路段报告的 mph。用户搜索将是“我想查看过去 3 个月内周五这条路的平均速度”

然后,地图引擎会根据平均速度根据图例对其进行渲染。地图引擎需要知道每条道路/多段线的颜色,因此如果在地图上查看 X 条道路,它需要 X 值以及 X 多段线。

【问题讨论】:

  • 您的问题有很多属性,例如“100% 读取”和聚合,这表明数据仓库/星型模式可能比引擎选择提供更多好处。如果没有关于您的数据的一些基础知识,特别是时间数据,它的基数与多边形数据,很难提出任何远程具体的建议。你能提供一些时间数据的例子吗?给定多边形是否有多个时间记录,或者每个时间条目都有唯一的多边形?
  • 数据仓库设计在这里通常有意义的原因(除其他外)是您最小化事实表行的大小,从而最大化 I/O 吞吐量和可以缓存在内存中的行数。分段时间维度可能有意义且有很大帮助,但这取决于您在聚合期间如何对数据进行分组以及关系的具体情况。
  • 更新了时间数据细节
  • 值得注意的是,我查看了 amazon redshift ,因为它基于 postgres。但是它不支持postGIS插件,所以它没有任何空间索引能力。
  • 我同意@AaronLS 关于维度模式的观点。如果不出意外,它绝对值得一试 - 您已经在使用 SQL Server,假设它可能 让您失败并跳槽到未知的地方是没有意义的。此外,SO 规则禁止询问软件/工具建议的问题,因此您最好编辑此问题以专注于“我可以/我如何在 SQL Server 中执行此操作”以避免它被标记和关闭。如果您发现 SQL Server 无法做到这一点,您总是可以单独提出一个问题,询问 MongoDB 是否适合您的要求。

标签: sql-server mongodb database-design data-warehouse database-performance


【解决方案1】:

数据只会每年写入一次,基本上是 100% 读取。

...对 timedata 的大多数查询都需要一个时间范围内的 AVERAGE

这两件事,100% 读取和聚合听起来像数据仓库/星型结构,值得探索。要正确构建这样的结构,需要了解很多概念,但我们可以找到潜在的设计。

时间数据包括在该路段报告的 mph 每隔 15 分钟。用户搜索将是“我想查看 过去 3 个月内周五这条路的平均速度"

如果您说每隔 15 分钟,我假设我们可能有 5 个人在下午 1:15 到下午 1:30 之间经过该路段,因此该时间段有 5 条记录。

对于以前从未构建过数据仓库的任何人来说,这将是一个不舒服的练习,但作为一个对这些方法持怀疑态度并将其付诸实践的人,我已经看到你可以获得巨大的性能促进。换句话说,我是一个持怀疑态度的皈依者。通常,您会为操作事务保留标准化数据库,然后每晚/每周使用它填充您的数据仓库。

了解您将使用哪些类型的查询非常重要,因为我们设计了星型结构以适应它们。不过,它并没有严格限制查询,而且您仍然有很大的灵活性。有很多基于星型结构的通用分析/OLAP 工具,它们的灵活性就是证明。

日期/时间维度 我们要做的第一件事是创建时间和日期维度。时间维度中的每一行代表一个 15 分钟的间隔。我会在某处记录开始/结束包含/排他性,因此围栏上的任何时间都明确包含/排除。它只有 96 行,一天中每 15 分钟间隔一个。

Id,StartTime(inclusive),EndTime(exclusive)
 1, 0:00, 0:15
 2, 0:15, 0:30
...
95,23:30,23:45
96,23:45,24:00

日期维度可以设计成几种不同的方式。为了最大限度地提高分析灵活性,我们通常在我们的数据涵盖的每一天都有一行。对于任何具有标准化数据库设计背景的人来说,这似乎很荒谬,但这是数据仓库中相当标准的做法,而且数据仓库书籍中的整章都解释了原因。有一些脚本可以帮助您生成日期维度中的条目。如果您的数据涵盖 2000 年,并且您计划在未来几年内重新加载数据库,那么您将为 2000 年到 2020 年的每一天创建条目,这只有 7300 行(20 年 * 365 天)。考虑到这可以很容易地缓存在非常小的内存中。

Id,Date(date),Year(smallint),Month(tinyint),Day(tinyint),MonthName,MonthAbbreviation,DayOfWeekNumber(tinyint),DayOfWeekName....
1000,2015,5,15,... 
1001,2015,5,16,...
1002,2015,5,17,...

所有额外列(例如 DayOfWeekNumber 和 DayOfWeekName)的原因是为了支持对这些属性或组合进行非常简单的聚合。使groupby DayOfWeekNumber 变得非常简单,因此您可以以不同的方式进行趋势分析。

多边形维度 对于多边形维度,每个路段会有一行。我做出这个选择是因为多个时间条目将共享一个 poly 段,因此我们希望下面事实表中的 polyId 进行分组。

速度事实表 该表将是具有大量记录的表。事实表中的每一行都应该尽可能小。这最大限度地提高了 I/O 吞吐量、聚合速度以及尽可能多地在内存中缓存的能力。

例如,DateId 应该是smallint,因为 2 个字节足以表示 32767 个 ID,远远超过 20 年数据所需的 7300 个以及 60 年以上的空间。 TimeId 将是一个小整数。人们会说存储很便宜,但这不是驱动因素。 I/O 吞吐量和缓存利用率是小行大小很重要的原因(因此每页的行数)。

RoadSegmentId, TimeId, DateId, Speed
1,1,1,45
1,1,1,47
1,1,1,92
1,2,1,55
1,2,1,67
1,2,1,91
2,1,1,55
2,2,1,67
2,2,1,91
...

查询

“我想查看过去 3 个月内周五这条路的平均速度”

Select rsd.Polygon, Avg(f.Speed)
From SpeedFacts f
Inner Join DateDimension dd on f.DateId = dd.Id
Inner Join RoadSegmentDimension rsd on f.RoadSegmentId = rsd.Id
Where dd.DayOfWeekNumber = 5 and dd.Date > '3/6/2015' --you could of course get current date, subtract 3 months to make this more generic
   and rsd.Polygon.STIntersects(@boundingBox)
Group By f.RoadSegmentId, rsd.Polygon

所以有几点需要注意。 SQL server 选择如何优化这一点很难不经过测试就说出来,但该结构允许一条看似有效的路径:

  1. 从大于 2015 年 3 月 6 日和 DayOfWeekNumber 5 的 DateDimension 行中选择。这些行中的每一个都应该有一个索引,并且页面读取应该具有良好的利用率,因为行的物理排序会将它们放在相同的页面中。这会产生 12 行,每周一行。
  2. 现在 SQL Server 只有 12 个 DateId,并且可以使用 SpeedFacts.DateID 上的索引来缩小 SpeedFacts 中要读取的行/页的范围。

SpeedFacts.DateId 索引比我们有一个实际日期类型的 SpeedFacts.Date 列要小很多。所以数百万行的索引要小得多,因此 SQL Server 可以更快地读取它。从而缩小它对事实表感兴趣的行数。

唯一让我担心的是取决于您的数据模式,这可能不会消除对 RoadSegmentDimension 中的每个多边形执行STIntersects 的需要。如果您有稀疏的速度测量,其中很多路段在某些时间范围内没有任何读数,那么加入 RoadSegementDimension 的第三步可能会消除很多多边形,然后只需要在剩余的多边形上应用 StIntersects。

无论如何,希望它可以在执行空间比较之前非常有效地缩小事实行的数量。

无论哪种方式,我认为您会看到这种结构比更传统的结构具有显着的性能,并且可以打赌,性能增益大于引擎之间的任何差异。

我对 MongoDB 了解不多,但我使用过其他风格的 NoSQL/document/json 数据库,我不确定这种引擎是否真的适合这种类型的分析。

【讨论】:

  • 完全同意 - 而且,OP 并没有说 如何 人们对此进行查询。 SQL Server 意味着您至少有一些可用的 MS BI 堆栈。 SSAS 是 SQL Server 的一部分,很好地位于维度模型之上,为最终用户提供数据分析/数据查询功能。多维数据集可以是非常用户友好的 - 特别是如果用户已经习惯于透视表,并且 MDX 是查询的一个选项。如果符合其他要求,可能是一种大幅提高查询性能的方法。
  • 这很棒。我将阅读有关星型结构的更多信息并致力于实现原型。我还可以索引客户端和/或美国各州的数据,以减少 STIntersects 必须做的工作。我们将拥有少于 255 个客户,因此可以使用 tinyint,但一些客户重叠(我们有一个州客户和该州内的一个县)。我不确定执行 OR 语句是否会损害性能,例如 clientid = 10 OR 4,但我会测试并找出答案!
  • 是的,您实际上可以将 Excel 数据透视表和过滤器面板直接映射到星型模式,或使用 SSAS。 SSAS 是一种 OLAP 引擎。无论哪种方式,您都可以让用户以交互方式准确地执行这些类型的查询:insightinformation.net/wp-content/uploads/2013/08/…
  • 对于日期维度,我为什么不想使用“智能键”作为 YYYYMMDD 形式的定义整数。这难道不允许人们在不需要加入日期维度的情况下根据日期查询事实表吗?此外,SQL SERVER 支持 SMALLDATETIME,它仅用 4 个字节表示日期和时间,这不会比 short int 或 YYYYMMDD int 更好,还是 SMALLDATETIME 存在连接性能问题?
  • @ParoX 智能钥匙的优点/缺点很多。分析工具不太可能以这种方式利用它们,因为它们不是维度属性,而且“可读性”只会使后端用户受益。我个人的观点是反对他们,但是来自数据仓库领域知名权威 Kimball 的两篇文章在这些文章中概述了一些优缺点:kimballgroup.com/2006/11/…kimballgroup.com/2004/02/…
【解决方案2】:

如果您最终想要更深入地探索 Geohash 路线,这里有一个您可能感兴趣的针对 TSQL 的 Geohash 相关函数的更充实的实现。

关于 R-Tree 索引与基于整数的 Geohashes 性能之间的争论,我对大数据场景有不同的经验。使用索引数组、哈希表和树之间的权衡与软件工程中的权衡相同。每个都有优于其他两个的用例。 R-Tree Indexes 与 Geohash 聚类也是如此。

【讨论】:

    猜你喜欢
    • 2017-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-14
    • 2016-04-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多