2011-04-12 19 views
9

我们有> 200,000,000行的平面文件(CSV),我们将其导入包含23个维度表的星型模式。最大的维度表有300万行。目前我们在一台计算机上运行导入过程,大约需要15个小时。由于这段时间太长,我们想利用40台电脑等东西进行导入。如何有效地利用10多台计算机导入数据

我的问题

我们怎样才能有效地利用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 
+1

如果无法将问题简化为较小的子问题,则无法从添加的计算机中获益,因为它们都是解决相同问题所必需的。您没有提供关于您的23D映射(或导向它的数据)的性质的足够信息,以便我为您提供除此以外的任何指示。 – jmz 2011-04-12 08:11:44

+1

标记为脱离主题 – 2011-04-12 08:20:54

+1

CVS的大小(以字节为单位)是多少? – ern0 2011-04-20 08:14:00

回答

3

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

那么,你应该尝试是这样的:

  1. 安装在每台计算机上的本地数据库。这将消除网络延迟。

  2. 在每台计算机上加载不同部分的数据。尝试给每台电脑相同的块。如果由于某种原因不容易,请给每台计算机,比如说10,000行。当他们完成后,给他们下一个块。

  3. 与DB工具转储数据

  4. 加载所有转储到一个DB

确保您的装载机工具可以将数据导入到已经包含数据的表。如果你不能这样做,请检查你的数据库文件中的“远程表”。许多数据库允许从另一个数据库服务器在本地可见。

这让你像insert into TABLE (....) select .... from REMOTE_SERVER.TABLE

如果您需要主键(你应该)运行命令,你也必须导入到本地数据块期间分配的PK问题。我建议将PK添加到CSV文件。

[编辑]为您编辑检查完毕后,这里是你应该尝试什么:

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

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

    这是一个相当便宜的进程(一对夫妇甚至对大文件分钟)。它给你的ID值文件。

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

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

  3. 将大文件拆分为40个块,并在每台机器上加载它们。

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

  4. 使用备份/恢复或远程表来合并结果。

    或者,更好的办法是将数据保存在40台机器上,并使用并行计算算法分割工作并合并结果。这就是Google可以在几毫秒内从数十亿网页创建搜索结果的方式。

请参阅here for an introduction

+0

此解决方案的问题在于,在导入所有转储到单个数据库时,没有简单的方法来合并维度表。一维表中对应于ID 1的字符串可能对应于另一维表中的ID 77。这也意味着事实表中的ID不兼容。 – 2011-04-12 08:44:37

+0

正如我所说:在将ID加载到维度表之前,将这些ID分配给CSV行。不要使用自动分配的标识列(或者不要为这些列传递'NULL';那么数据库不会为您生成密钥)。 – 2011-04-13 09:58:58

+0

如何将ID分配给CSV行?你的意思是我需要在创建CSV文件时分配这个吗?如果你是这个意思,那么我可以说这是不可能的,因为创建过程。 – 2011-04-20 08:08:14

2

这是一个非常通用的问题,并没有考虑后端数据库考虑在内。在不能处理负载的数据库后端上启动40或1000台机器将不会带来任何结果。这样一个问题的确要广泛地以特定的方式来回答它。你应该首先与你的组织中的人员联系,并且具有足够的数据库级别的技能,然后回来一个更具体的问题。

+0

我是我们两人组织中的那个人。你能否指点我一个可以让问题更具体的方法。目前我们还没有选择数据库引擎,这就是我没有指定的原因。我认为这是一个普遍问题,因此我以一种通用的方式提出问题,以便其他人可以利用该解决方案而不管数据库技术如何 – 2011-04-12 08:11:06

+0

我们对您的输入数据一无所知。我们不知道您的数据如何分区。我们对输入数据的约束一无所知....抱歉,超出了Stackoverflow的范围。您应该考虑获得处理大型系统的专业帮助。 – 2011-04-12 08:20:13

+0

我已更新我的问题。所以希望这会让这个问题更清楚。 – 2011-04-20 08:24:16

2

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

问题:现在需要15个小时。你知道哪一部分过程花费时间最长吗? (读取数据,清理数据,保存表格中的读取数据,索引...你将数据插入到无索引表格和索引后,对吧?)

要在N台计算机之间分割这个作业,这是一个信封设计):

  • 有一个“中央”或主数据库。使用它来改变整个流程,并保留最终的完整仓库。
  • 它包含了所有的X文件和所有N-1(不包括自身)的列表“工人”数据库​​
  • 每个工人数据库以某种方式连接到主数据库(只是如何依赖于RDBMS,你还没有指定)
  • 启动并运行时,“就绪”辅助数据库轮询master数据库以处理文件。master数据库将文件分发给工作系统,确保一次不会有多个文件被处理。 (必须跟踪加载给定文件的成功/失败;观察超时(工作失败),管理重试。)
  • 工作人员数据库具有星型模式的本地实例。分配文件时,它清空模式并从该文件加载数据。 (对于可伸缩性,一次可能需要加载几个文件?)在这里为包含在该文件中的数据完成“第一阶段”数据清理。
  • 加载时,主数据库将更新为该员工的“准备好的眩目”,并进入等待模式。
  • 主数据库拥有完成加载数据的工作数据库自己的待办事项列表。它依次处理每个等待工作人员组;当一个工作集已经被处理时,工作者被重新设置为“检查是否有另一个文件要处理”模式。
  • 在进程开始时,master数据库中的星型模式被清除。第一组加载可能只是逐字复制。
  • 对于第二组和更多,必须读取和“合并”数据 - 抛出多余的条目,通过一致的维度合并数据等。适用于所有数据的业务规则,不是一次一个集合,必须是现在也完成了。这将是“第二阶段”数据清理。
  • 再次,对每个工作人员数据库重复上述步骤,直到所有文件都已上传。

优点:

  • 阅读/从文件数据转换成数据库和操作的方式“第一级”清洗获取到N个计算机向外扩展。
  • 理想的情况下,一些工作(“第二阶段”,合并数据集)是留给主数据库

限制:

  • 大量数据首先被读入工人数据库,然后再读(尽管采用DBMS本机格式),但网络上的主数据库是可能的阻塞点。一切都必须经过这里。

快捷键:

  • ,当一个工作站“在检查”的一个新的文件,它可以刷新已加载在主数据的本地存储,并添加数据清理方面的考虑基于这很可能这到它的“第一阶段”工作(即它知道代码5484J已经被加载,所以它可以将其过滤掉并且不传递回主数据库)。
  • 其他RDBMS的SQL Server表分区或类似的物理实现技巧可能可能被用来取得良好效果。
  • 其他快捷方式很可能,但它完全取决于正在实施的业务规则。

不幸的是,没有进一步的信息或对系统和数据的了解,人们无法判断这个过程是否会比“一揽子解决方案”更快或更慢。在一天结束时,它很大程度上依赖于您的数据:它是否提交“分而治之”技术,还是必须通过单个处理实例运行?

2

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

您计划使用23维starscheme的数据库是什么?导入可能不是唯一的性能瓶颈。您可能想要在分布式主存储器系统中执行此操作。这避免了很多的输入问题。

您应该调查是否有高度相关的尺寸。

一般来说,对于具有大尺寸的23维星型方案,标准关系数据库(SQL Server,PostgreSQL,MySQL)在数据仓库问题上表现极差。为了避免必须进行全表扫描,关系数据库使用物化视图。有23个维度,你无法承受足够的。分布式主内存数据库可能能够进行足够快的全表扫描(在2004年,我在德尔福的Pentium 4 3 GHz上做了大约800万行/秒/线程)。 Vertica可能是另一种选择。

另一个问题:当你压缩文件时文件有多大?这可以为您可以执行的标准化量提供很好的一阶估计。

我看了你的其他问题。这看起来不像PostgreSQL(或MySQL或SQL服务器)的良好匹配。您愿意等待查询结果多长时间?

0

在另一方面,你可以利用的Windows Hyper-V的云计算插件的Windows服务器:http://www.microsoft.com/virtualization/en/us/private-cloud.aspx

10

你可以考虑使用一个64位散列函数为每个字符串生成bigint ID,而不是使用顺序ID。

使用64位散列码,可以在发生碰撞的几率为0.0031%之前,在散列表中存储2 ^(32-7)个或超过3000万个项目。

这将允许您在所有节点上拥有相同的ID,并且在'dispatch'和'merge'阶段之间服务器之间没有任何通信。

您甚至可以增加位数以进一步降低碰撞几率;只有你不能在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

+1

这是一个好主意。尽管如此,这不会导致事实表的规模增加一倍。有什么方法可以在以后的步骤中将列转换为32位? – David 2011-05-20 08:06:28

+0

@大卫,非常有趣的问题。合并已处理的块后,您将回到单机环境,在该环境中可以立即检测到PK冲突,并且可以轻松处理。在这一点上,返回到32位数字的最快方法是Hash Truncation(请参见http://www.ietf.org/proceedings/63/slides/hash-4.pdf的幻灯片2,“截断H的结果可能是 优选开发/部署产生长度为Np的消息摘要的新算法 )。这个额外的步骤将以处理时间为代价节省磁盘空间;这取决于什么是最重要的。 – magma 2011-05-24 23:25:52

1

野鲮,

我建议你通过FIRST sumarising数据消除很多来自负载的工作,在数据库之外。我在Solaris unix环境中工作。我会倾向于一个korn-shell脚本,其中cut将文件分成更多可管理的块,然后将这些块划分为我的两个OTHER服务器。我会使用nawk脚本处理块(nawk有一个高效的散列表,他们称之为“关联数组”)来计算不同的值(维度表)和Fact表。只需将每个新名称与增量为此维度关联起来,然后编写事实。

如果通过命名管道执行此操作,则可以在“主机”计算机坐在那里将数据直接加载到表格中时,即时推送,处理远程数据和回读数据。

请记住,无论您处理200,000,000行数据(有多少Gig?),都需要一些时间。听起来像是你有一些乐趣。阅读其他人如何提出解决这个问题很有意思......古老的格言“有不止一种方法可以做到这一点!”从来没有如此真实。祝你好运!

干杯。基思。

0

看来您的实现效率非常低,因为它的加载速度低于1 MB /秒(50GB/15小时)。

在现代单台服务器(2x Xeon 5690 CPU + RAM,足以容纳所有尺寸的散列表加载8GB内存)的适当实现应该至少提供10倍的速度,即至少10MB /秒。

相关问题