在超快速的数据库中扫描十亿行


9

背景

本地数据库包含近13亿个唯一行。每行都与特定的纬度和经度(位置)间接相关。每行都有一个日期戳。

用例

问题如下:

  1. 用户设置开始/结束日期以及值的范围(例如100到105)。
  2. 系统将按位置分组与给定日期匹配的所有行。
  3. 系统执行确定在那些日期期间具有落入给定值范围的统计可能性的位置。
  4. 系统向用户显示所有匹配的位置。

这是速度和规模的问题。

您能想到哪一种最便宜的解决方案体系结构可使这种系统在五秒钟内为用户检索结果?

当前系统

当前环境是:

  • PostgreSQL 8.4(可以升级;不能选择切换数据库)
  • R和PL / R
  • XFS文件
  • WD VelociRaptor
  • 8 GB RAM(Corsair G.Skill; 1.3 GHz)
  • 四核原装Intel 7(2.8 GHz)
  • Ubuntu 10.10

可以接受硬件升级。

更新-数据库结构

表中的数十亿行类似于:

id | taken | location_id | category | value1 | value2 | value3
  • id-主键
  • 采取-分配给行的日期
  • location_id-参考纬度/经度
  • 类别-数据描述
  • value1 .. 3-用户可以查询的其他值

taken列通常location_id是每个日期的连续日期,有时每个位置都有1800至2010年的数据(大约77,000个日期,许多重复,因为每个位置都具有相同的日期范围内的数据)。

有七个类别,并且这些表已经按类别划分(使用子表)。每个类别包含约1.9亿行。在不久的将来,每个类别的行数将超过10亿。

大约有20,000个地点和70,000个城市。这些位置通过纬度和经度与城市相关联。将每个位置分配给特定城市意味着找到城市的边界,这不是一件容易的事。

主意

我的一些想法包括:

  • 查找托管数据库的云服务。
  • 创建一个SSD RAID条带(出色的视频)。
  • 创建一个表,按城市合并所有位置(预先计算)。

谢谢!


10
“切换数据库不是一种选择”很好地消除了大多数解决方案。祝好运!
Steven A. Lowe

1
如果没有更多有关这些记录的确切信息,很难说。另外,您是否正在寻找5秒的最坏情况(这可能意味着检查的每条记录和零个位置都匹配)?
盖·西顿

2
@戴夫:当前系统需要多少时间?当前系统是否使用PostGIS?是location_id一个geographygeometry,或者指的是第二个表?是location_id列索引?
rwong 2011年

1
@Thorbjørn&@Darknight-在“想法”部分中,我列出了预先计算的内容,这会将数据减少到每个城市每天(每个类别)一个值。我想,该计算可能每年重复一次,甚至每月一次。如果没有其他可能性,这是我的计划(计算可能需要数周)。
戴夫·贾维斯

1
@Dave,有很多可能性,但问题是与您相关的是什么。您是否调查了当前的瓶颈所在?

Answers:


12

最重要的是要绝对确定给定数量的代表性请求的瓶颈所在,因为您无法切换数据库。

如果进行全表扫描,则需要适当的索引。

如果等待I / O,则需要更多的内存用于缓存(Jeff Atwood最近提到,台式机系统可以访问24 Gb系统)。

如果您等待CPU,则需要查看您的计算是否可以优化。

这需要一个尖尖的DBA帽子和一个操作系统帽子,但是值得确保确保您树立正确的树。


切片和切块的方式-即使每一行仅占用100个字节,13亿行= 121 GB。有了您所有的索引等等,我相信这会更多。在一个盒子上,除非您在SSD +吨的RAM周围有一些严肃的硬件,否则您的速度将会很慢。便宜的方法是跨框扩展。
Subu Sankara Subramanian

4
@Subu,您要分发吗?现在您有两个问题……

嘿-我同意:)但是便宜!
Subu Sankara Subramanian

@Thorbjørn:谢谢您的时间和所有的帮助。我想我会将每个类别的数据集减少到2500万行,然后在该日期应用索引。那应该将扫描减少到〜70000行(每天,范围限制为两周),这应该相当快。
戴夫·贾维斯

@Dave,您仍然需要知道瓶颈在哪里。了解它,而你不具备对。

4

如何根据日期戳将表分为位于不同主机上的多个部分?这是水平可伸缩的,并且只要您有足够数量的盒子,就可以在这些设置的顶部编写一个小型聚合引擎。

如果您看到日期戳变化太大,则可以根据位置进行分区-同样可以水平扩展。(希望它们不会增加更多的纬度/经度!)


谢谢你的想法。可能有77,066个日期,并且以后还会添加新的日期。我有一台机器。有20,000个位置,但按位置拆分将无济于事,因为要分析的数据跨越所有位置。
戴夫·贾维斯

使用云与上述解决方案有何不同?
加尼

这也是我的想法。某种水平分区,以便可以在所有分区上并行进行搜索。
davidk01 2011年

一天中的拆分可能是最有用的,这将导致2562个单独的表(366天x 7个类别)。
戴夫·贾维斯

4

最坏的情况是日期范围涵盖了数据库中的所有日期。

您希望在不到5秒钟的时间内在一台物理计算机上读取13亿条记录,并对每条记录与输入的值进行某种形式的分析。结果可能是所有位置,也可能是一个位置-您事先一无所知。

给定这些参数,我会说不可能。

只需查看您的硬盘驱动器即可:最大持续速率小于150MB / s。读取13亿条记录将花费5秒钟以上。在CPU方面,您将无法在5秒钟内对13亿条记录进行任何形式的统计分析。

您唯一的希望(tm :-))是根据用户输入的值找到某种查找功能,该功能将缩小搜索范围(缩小几个数量级)。您可以离线计算此查找功能。在不了解确切匹配条件的情况下,我认为没有人会告诉您如何执行该操作,但是一个示例是将值的范围划分为一些离散的间隔,并创建一个查找,为您提供该间隔中的所有记录。只要间隔足够小,您就可以在其中进行实际工作,例如,删除与用户输入的值不匹配的条目。基本上是为了时间而交易。

可以保留内存中的所有记录(或至少重要部分)。可能不是8GB。这将至少消除磁盘I / O部分,即使内存带宽可能不足以在5秒内扫描所有内容。无论如何,这是加快这类应用程序速度的另一种技术(与我之前的建议结合)。

您提到使用云服务。是的,如果您为足够的CPU和IO付出代价并在许多服务器之间对数据库进行分区,则可以蛮力/分割并征服它。


谢谢你的回答。根据我列出的想法,硬件升级是一个考虑因素。低于750美元的解决方案将是理想的选择。
戴夫·贾维斯

2

我对rwong的问题发表第二个评论:PostgreSQL提供了适当的索引类型和工具(GIST索引,GIN索引,Postgis,Geometrical类型),以便可以沿着这些标准搜索地理数据和与日期时间相关的数据而没有太多问题。

如果您对这些条件的查询花费了几秒钟,则可能意味着没有使用此类索引。您能否确认已对这些问题进行了适当的调查?


谢谢。使用btree将七个子表聚集在位置,日期和类别上。我记得去年我研究了GIN索引,但它们没有(或没有帮助)。
戴夫·贾维斯

2
考虑到您正在寻找的搜索类型,基于B树的索引位置并不是一丁点有用的。您需要一个与所需运算符一起使用的倒排索引,在Postgis的情况下,这通常意味着GIST。您可能需要突出一些缓慢的查询...
Denis de Bernardy 2011年

1

考虑到您使用PostgreSQL和纬度/经度数据,您当然也应该使用PostGIS,这样您就可以向数据库中添加GiST空间索引以帮助加快速度。

我有一个这样的表(有35万行),其配置比您的表小得多(2核,几乎没有2Gb RAM),但搜索时间不到一秒钟。


0

也许您可以像Essbase那样使用其OLAP架构打破关系模型: Essbase Wikipedia

我的意思是每个城市创建一张表,最终得到1000多个表。不是您建议的一张桌子,而是很多。按日期和位置索引每个表。很多表,很多索引->更快。


感谢您的来信。有超过70,000个城市,并且特定城市区域内有许多不同的纬度/经度值。
戴夫·贾维斯

@Dave:您可以为城市建立一个voronoi图并将经/纬度值分类为镶嵌图吗?(即,听起来似乎是偶然的。)然后,在查找过程中,您将搜索其细分涉及查询的纬度/经度范围的所有城市。如果voronoi镶嵌速度太慢,则可能值得尝试使用方盒(例如lat 5 lat x 5 lon)。
rwong 2011年

0

至于您想找到一个托管数据库的云服务的想法,您是否遇到过SimpleGeo?他们只是在存储服务上剪了一条丝带,显然“经过特别调整,可以真正,非常快地存储和查询位置数据”-尽管针对数十亿行的存储和查询成本可能使这种方法不可行。


-2

您期望自行车在高速公路上行驶。当前,您正在寻找仅解决此问题的解决方案,您没有预见到该问题,如果您有20亿条记录怎么办?可扩展性必须解决。答案是简单使用对象数据库。例如系统间缓存

相信你我我不是来自系统间;-)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.