我们有包含> 200,000,000行的平面文件(CSV),我们将其导入具有23个维度表的星型模式。最大的维度表有300万行。目前我们在一台计算机上运行导入过程,大约需要15个小时。由于时间太长,我们希望利用40台计算机之类的东西进行导入。
我的问题
我们如何才能有效利用40台计算机进行导入。主要担心的是,在所有节点上复制维度表需要花费大量时间,因为它们需要在所有节点上相同。这可能意味着如果我们将来使用1000台服务器进行导入,由于服务器之间广泛的网络通信和协调,它实际上可能比使用单一服务器慢。
有没有人有建议?
修改
以下是CSV文件的简化:
"avalue";"anothervalue"
"bvalue";"evenanothervalue"
"avalue";"evenanothervalue"
"avalue";"evenanothervalue"
"bvalue";"evenanothervalue"
"avalue";"anothervalue"
导入后,表格如下所示:
dimension_table1
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
答案 0 :(得分:10)
您可以考虑使用64位哈希函数为每个字符串生成bigint
ID,而不是使用顺序ID。
使用64位哈希码,您可以在哈希表中存储2 ^(32 - 7)或超过3000万个项目,然后发生碰撞的可能性为0.0031%。
这将允许您在所有节点上拥有相同的ID,在“dispatch”和“merge”阶段之间的服务器之间无需任何通信。
您甚至可以增加位数以进一步降低碰撞几率;只是,您将无法在64位整数数据库字段中生成结果哈希值。
请参阅:
http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash
答案 1 :(得分:3)
将CSV数据加载到数据库中的速度很慢,因为它需要读取,拆分和验证数据。
所以你应该尝试的是:
在每台计算机上设置本地数据库。这将消除网络延迟。
在每台计算机上加载不同部分的数据。尝试为每台计算机提供相同的块。如果由于某种原因这不容易,请给每台计算机,比如说,10,000行。完成后,给他们下一个块。
使用数据库工具转储数据
将所有转储加载到单个数据库
确保您的加载程序工具可以将数据导入已包含数据的表中。如果您无法执行此操作,请检查数据库文档中的“远程表”。许多数据库允许从本地可见的另一个DB服务器创建表。
这允许您运行insert into TABLE (....) select .... from REMOTE_SERVER.TABLE
如果您需要主键(并且您应该),则在导入本地数据库期间也会出现分配PK的问题。我建议将PK添加到CSV文件中。
[编辑] 检查完修改后,您应该尝试以下操作:
编写一个小程序,在CSV文件的第一和第二列中提取唯一值。这可能是一个简单的脚本,如:
cut -d";" -f1 | sort -u | nawk ' { print FNR";"$0 }'
这是一个非常便宜的过程(即使对于大文件也要几分钟)。它为您提供了ID值文件。
编写一个程序,读取新的ID值文件,将它们缓存在内存中,然后读取巨大的CSV文件,并用ID替换这些值。
如果ID值文件太大,只需对小文件执行此步骤,然后将大量文件加载到所有40个每机器数据库中。
将大文件拆分为40个块并在每台机器上加载每个文件。
如果你有大量的ID值文件,你可以使用在每台机器上创建的表来替换剩下的所有值。
使用备份/恢复或远程表来合并结果。
或者,更好的是,将数据保存在40台计算机上,并使用并行计算中的算法来分割工作并合并结果。这就是谷歌可以在几毫秒内从数十亿网页创建搜索结果的方式。
答案 2 :(得分:2)
这是一个非常通用的问题,不考虑数据库后端。在无法处理负载的数据库后端上使用40或1000台计算机进行解雇将不会给您带来任何帮助。这个问题确实是广泛的,以特定的方式回答它。你应该首先在组织内部与人员取得联系,然后再提出更具体的问题。
答案 3 :(得分:2)
假设有N台计算机,每个X文件大约有50GB文件,目标是在最后有1个包含所有内容的数据库。
问题:现在需要15个小时。你知道这个过程的哪个部分花费的时间最长吗? (读取数据,清理数据,保存表中的读取数据,索引......您将数据插入到未编制索引的表中并在之后编制索引,对吗?)
要在N台计算机中分配这份工作,我会做类似的事情(这是一种背后的设计):
优点:
限制:
快捷方式:
不幸的是,如果没有进一步的信息或对所涉及的系统和数据的理解,人们无法判断这个过程是否会比“全部一箱”解决方案更快或更慢。在一天结束时,它很大程度上依赖于您的数据:它是否提交“分而治之”技术,还是必须通过单个处理实例运行?
答案 4 :(得分:2)
最简单的事情是让一台计算机负责分发新的维度项ID。每个维度可以有一个。如果维度处理计算机位于同一网络上,您可以让它们广播该ID。这应该足够快。
您计划使用哪种数据库使用23维星图?导入可能不是唯一的性能瓶颈。您可能希望在分布式主内存系统中执行此操作。这避免了很多物质化问题。
您应该调查是否存在高度相关的维度。
一般来说,对于尺寸较大的23维星型方案,标准关系数据库(SQL Server,PostgreSQL,MySQL)在数据仓库问题上表现极差。为了避免必须进行全表扫描,关系数据库使用物化视图。有23个尺寸,你买不起它们。分布式主内存数据库可能能够足够快地进行全表扫描(2004年,我在Delphi中的奔腾4 3 GHz上做了大约800万行/秒/线程)。 Vertica可能是另一种选择。
另一个问题:拉链时文件有多大?这为您可以进行的标准化量提供了良好的一阶估计。
[编辑]我看了你的其他问题。对于PostgreSQL(或MySQL或SQL服务器)来说,这看起来不太匹配。你愿意等多久查询结果?
答案 5 :(得分:1)
鲮,
我建议你在数据库之外通过sussrising数据FIRST来消除大量的工作。我在Solaris unix环境中工作。我会倾向于一个korn-shell脚本,cut
将文件放到更可管理的块中,然后将这些块平均地存放到我的两个OTHER服务器上。我使用nawk脚本处理块(nawk有一个有效的哈希表,它们称之为“关联数组”)来计算不同的值(维度表)和Fact表。只需将每个新名称与一个incrementor-for-dimension关联起来,然后写下Fact。
如果您通过命名管道执行此操作,您可以“动态”推送,远程处理和回读数据,而“主机”计算机就在那里直接将其加载到表格中。
请记住,无论你使用200,000,000行数据做什么(它有多少千兆?),都需要一些时间。听起来像是在享受一些乐趣。阅读其他人如何提出解决这个问题的方法很有意思......古老的格言“有不止一种方法可以做到这一点!”从未如此真实。祝你好运!
干杯。基思。
答案 6 :(得分:0)
另一方面,您可以使用适用于Windows Server的Windows Hyper-V云计算插件:http://www.microsoft.com/virtualization/en/us/private-cloud.aspx
答案 7 :(得分:0)
似乎您的实现效率非常低,因为它的加载速度低于1 MB /秒(50GB / 15小时)。
在现代单一服务器上正确实施(2x Xeon 5690 CPU + RAM足以支持哈希表中加载的所有维度+ 8GB),应该至少提高10倍的速度,即至少10MB /秒。