如何有效利用10台以上的计算机导入数据



我们有超过200000000行的平面文件(CSV(,我们将其导入到具有23个维度表的星形模式中。最大的维度表有300万行。目前,我们在一台计算机上运行导入过程,大约需要15个小时。由于时间太长,我们想用大约40台电脑来进口。

我的问题

我们如何才能有效地利用40台计算机进行导入。主要担心的是,在所有节点上复制维度表将花费大量时间,因为它们需要在所有节点中相同。这可能意味着,如果我们在未来使用1000台服务器进行导入,由于服务器之间广泛的网络通信和协调,实际上可能比使用单个服务器慢

有人有什么建议吗?

编辑:

以下是CSV文件的简化:

"avalue";"anothervalue"
"bvalue";"evenanothervalue"
"avalue";"evenanothervalue"
"avalue";"evenanothervalue" 
"bvalue";"evenanothervalue"
"avalue";"anothervalue"

导入后,表格如下所示:

尺寸表1

id  name
1   "avalue"
2   "bvalue"

dimension_table2

id  name
1   "anothervalue"
2   "evenanothervalue"

事实表

  dimension_table1_ID       dimension_table2_ID
    1                      1
    2                      2
    1                       2
    1                       2              
    2                       2
    1                       1

您可以考虑使用64位哈希函数为每个字符串生成bigint ID,而不是使用顺序ID。

使用64位哈希码,在发生冲突的几率为0.0031%之前,您可以在哈希表中存储2^(32-7(或超过3000万个项目。

这将允许您在所有节点上具有相同的ID,在"调度"one_answers"合并"阶段之间的服务器之间没有任何通信。

你甚至可以增加比特的数量来进一步降低碰撞的几率;只是,您将无法使生成的哈希适合64位整数数据库字段。

参见:

http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash

http://code.google.com/p/smhasher/wiki/MurmurHash

http://www.partow.net/programming/hashfunctions/index.html

将CSV数据加载到数据库中很慢,因为它需要读取、拆分和验证数据。

所以你应该试试这个:

  1. 在每台计算机上设置一个本地数据库。这将消除网络延迟。

  2. 在每台计算机上加载不同部分的数据。试着给每台计算机相同的区块。如果出于某种原因,这并不容易,那么给每台计算机,比如说,10’000行。完成后,给他们下一块。

  3. 使用数据库工具转储数据

  4. 将所有转储加载到单个DB 中

确保您的加载器工具可以将数据导入已经包含数据的表中。如果不能做到这一点,请查看DB文档中的"远程表"。许多数据库允许使来自另一个数据库服务器的表在本地可见。

这允许您运行类似insert into TABLE (....) select .... from REMOTE_SERVER.TABLE 的命令

如果您需要主键(而且您应该这样做(,那么在导入到本地DB的过程中也会遇到分配PK的问题。我建议将PKs添加到CSV文件中。

[EDIT]检查您的编辑后,以下是您应该尝试的:

  1. 编写一个小程序,提取CSV文件第一列和第二列中的唯一值。这可能是一个简单的脚本,比如:

     cut -d";" -f1 | sort -u | nawk ' { print FNR";"$0 }'
    

    这是一个非常便宜的过程(即使对于巨大的文件也需要几分钟(。它为您提供ID值文件。

  2. 编写一个程序,读取新的ID值文件,将其缓存在内存中,然后读取巨大的CSV文件,并用ID替换这些值。

    如果ID值文件太大,只需对小文件执行此步骤,然后将大文件加载到每台机器的所有40个DB中。

  3. 将这个巨大的文件分成40个块,并将每个块加载到每台机器上。

    如果您有巨大的ID值文件,您可以使用在每台机器上创建的表来替换所有剩余的值。

  4. 使用备份/还原或远程表合并结果。

    或者,更好的是,将数据保存在40台机器上,并使用并行计算的算法来拆分工作和合并结果。这就是谷歌如何在几毫秒内从数十亿个网页中创建搜索结果。

请参阅此处了解介绍。

这是一个非常通用的问题,没有考虑数据库后端。在数据库后端用40或1000台无法处理负载的机器进行射击不会给你带来任何好处。这样一个问题要用一种具体的方式来回答,实在太宽泛了。。你应该先与组织内部有足够DB级别技能的人取得联系,然后再提出更具体的问题。

假设N台计算机,X个文件,每个文件大约50GB,目标是最后有一个包含所有内容的数据库。

问题:现在需要15个小时。你知道这个过程的哪一部分耗时最长吗?(读取数据,清理数据,将读取的数据保存在表中,编制索引……您正在将数据插入未编制索引的表中,然后编制索引,对吧?(

为了将这项工作分配给N台计算机,我会做一些类似的事情(这是信封背面的设计(:

  • 有一个"中央"或主数据库。用它来绘制整个过程,并保存最终完整的仓库
  • 它包含所有X文件和所有N-1(不包括它自己("工作者"数据库的列表
  • 每个辅助数据库都以某种方式链接到主数据库(只是方式取决于RDBMS,您尚未指定(
  • 当启动并运行时,"就绪"的辅助数据库会轮询master数据库以查找要处理的文件。主数据库将文件分配给工作系统,确保一次不会有多个文件被处理。(必须跟踪加载给定文件的成功/失败;注意超时(工作程序失败(,管理重试次数。(
  • 辅助数据库具有星形架构的本地实例。当分配一个文件时,它清空模式并从该文件加载数据。(为了可伸缩性,可能值得一次加载几个文件?(这里对该文件中包含的数据进行"第一阶段"数据清理
  • 加载时,master数据库会为该工作进程更新一个"就绪flagy",并进入等待模式
  • Master数据库有自己的待办事项列表,其中列出了已完成加载数据的worker数据库。它依次处理每个等待的工人集;当一个辅助集被处理后,该辅助集被设置回"检查是否还有其他文件要处理"模式
  • 在过程开始时,主数据库中的星形模式被清除。加载的第一个集合可能只是逐字复制
  • 对于第二组及以上的数据,必须读取并"合并"数据——丢弃冗余条目,通过一致的维度合并数据等。现在也必须执行适用于所有数据的业务规则,而不仅仅是一次一组。这将是"第二阶段"的数据清理
  • 再次,对每个工作者数据库重复上述步骤,直到所有文件都已上载

优点:

  • 将文件中的数据读取/转换为数据库,并进行"第一阶段"清理,这在N台计算机中得到了扩展
  • 理想情况下,主数据库只剩下很少的工作("第二阶段",合并数据集(

限制:

  • 许多数据首先被读取到工作数据库中,然后通过网络再次读取(尽管是DBMS本机格式(
  • Master数据库可能是一个瓶颈。一切都要经过这里

快捷方式:

  • 当工作站"签入"一个新文件时,它似乎可以刷新已经加载在master中的数据的本地存储,并将基于此的数据清理注意事项添加到其"第一阶段"工作中(即,它知道代码5484J已经加载,因此它可以将其过滤掉,而不将其传递回master数据库(
  • SQL Server表分区或其他RDBMS的类似物理实现技巧可能会产生良好效果
  • 可能还有其他捷径,但这完全取决于正在实现的业务规则

不幸的是,如果没有进一步的信息或对所涉及的系统和数据的了解,就无法判断这个过程最终会比"一个盒子做所有事情"的解决方案更快还是更慢。归根结底,这在很大程度上取决于你的数据:它是服从"分而治之"的技术,还是必须通过一个处理实例来运行?

最简单的事情是让一台计算机负责分发新的维度项id。每个维度都可以有一个。如果维度处理计算机在同一网络上,则可以让它们广播id。这应该足够快了。

你打算在23维星图中使用哪个数据库?导入可能不是唯一的性能瓶颈。您可能希望在分布式主内存系统中执行此操作。这就避免了很多物质化的问题。

您应该调查是否存在高度相关的维度。

一般来说,对于大维度的23维星形方案,标准关系数据库(SQL Server、PostgreSQL、MySQL(在数据仓库问题上的表现会非常糟糕。为了避免必须进行全表扫描,关系数据库使用物化视图。有23个尺寸,你买不起足够的。分布式主内存数据库可能能够足够快地进行全表扫描(2004年,我在Delphi中的Pentium 4 3 GHz上进行了大约800万行/秒/线程的扫描(。Vertica可能是另一种选择。

另一个问题是:压缩文件时文件有多大?这提供了一个很好的一阶估计量的归一化你可以做

[编辑]我看了你的其他问题。这看起来与PostgreSQL(或MySQL或SQL server(不太匹配。您愿意等待查询结果多长时间?

Rohita,

我建议您通过首先汇总数据库之外的数据来消除负载中的大量工作。我在Solaris unix环境中工作。我倾向于使用korn-shell脚本,它cut将文件划分为更可管理的块,然后将这些块平均分配给我的两个OTHER服务器。我会使用nawk脚本(nawk有一个高效的哈希表,他们称之为"关联数组"(来处理块,以计算不同的值(维度表(和事实表。只需将看到的每个新名称与该维度的增量关联起来,然后写下事实。

如果你通过命名管道来完成这项工作,你就可以"动态"地推送、远程处理和读回数据,而"主机"则直接将数据加载到表中。

记住,无论你对200000000行数据做什么(它是多少Gig?(,都需要一些时间。听起来你是来找乐子的。读一读其他人建议如何解决这个问题是很有趣的。。。古老的格言"有不止一种方法可以做到!"从未如此正确。祝你好运

干杯。基思。

另一方面,您可以使用适用于Windows Server的Windows Hyper-V云计算插件:http://www.microsoft.com/virtualization/en/us/private-cloud.aspx

您的实现似乎效率很低,因为它的加载速度低于1 MB/秒(50GB/15小时(。

在现代单服务器上的正确实现(2个Xeon 5690 CPU+RAM,足够用于哈希表中加载的所有维度+8GB(应使您的速度提高至少10倍,即至少10MB/秒。

最新更新