文件同步到数据库性能优化

zheng_pat 发布于 2013/09/15 16:29
阅读 1K+
收藏 5
问题描述:我们每天会定时从别人的服务器同步一个50W行的数据到本地服务器,使用txt文件保存。每行数据代表一个对象。我们使用文件流依次读取每行转成对象,再和数据进行对比,如果不存在就保存,如果存在但是属性发生了变更就更新。但是我测试了下时间需要5-7个小时,实在太慢了。不知道怎么去优化,如果用多线程是用在什么地方,现在发现文件读取和数据对比很慢,保存和更新很快,都是积累到1W条再执行sql。但是对象和数据库对比肯定是执行50W次这个太慢了。该怎么优化
加载中
0
中山野鬼
中山野鬼

楼主,虽然还是没理解你的整个业务场景,不过我怀疑就是“必须一条条”对比。那么这个,用楼上几位的方法(诸如分表,搞id等入库的方式),肯定不行。因为他们忽视了一个重要的问题,就是你的数据预处理的匹配工作。

搞了id,不能从id或者主键,对你的数据进行序化,仅能起到唯一性标识的作用,这对数据匹配没有任何价值。并发只能降低总体计算量的执行时间。并不能降低计算量。但你肯定要用到并发。

至于内存不内存的,这个就压根不相关了。不在内存里,在哪计算哈。

你的问题,基于数据库操作之上的,基本不靠谱。不信,你把你的数据量后面加个0,做个负载测试就知道。哈。

我的建议是还是分开处理。一个是数据并库。因为你要一对一匹配,所以可以看作两个数据库,合并新库的问题。无非是新增内容独立成表,还是附加在原表后。

分开处理的意思是,如果你必须按照行模式存储,可能你用的数据库需要这么做才能完成数据利用(入库后的查、改等),那么你的数据存在两套。一套是列存储方式,用于和新数据匹配,这个做并发,逻辑上容易设计。另一套是你正常的利用的行模式的存储。匹配后的整体数据再分表组织成行模式数据,进行利用。列模式,转行模式,分表实现,这个就是写c代码,还是很快的。

另一种思路,不用列模式匹配的,也不是不能做。要看数据匹配概率了。如果匹配概率大的话。则对原库分表。假设1,2,3,4,5,6.你的50w行数据,先开5个进程对表一进行匹配,表1中,不匹配的,开4个进程对表2匹配,表2中不匹配的数据,开3个进程对表三中进行匹配。

当然上面的数字只是个例子,实际看你数据重叠(匹配成功的概率)。这种做法,并不适合重叠度低的情况。

你的任务,除非数据比较公正(我自己的名词,哈,就是比较符合标准数据库的操作,属性关联很清晰),否则还是要自己写代码做比较。靠数据库的操作实现,肯定不靠谱。当然是用c/c++,其他语言就更不靠谱了。效率还不如数据库的标准操作,一一来过的好。

1
首席打酱油
首席打酱油

你抓的50W是全部数据吗?

如果是全部数据就别对比了,直接本地全删了,完全重新导入。如果不是全部数据,请说明你这50W数据是怎么来的,原理是什么

首席打酱油
首席打酱油
回复 @zheng_pat : 那不就得了 才50W数据 本地全删了 重新导入
zheng_pat
zheng_pat
是全部数据
0
huan
huan

如果有一个ID 判断数据是否存在就比较简单了。

将50W行数据全部写入数据库,然后将原表中有的,但是新表中不存在的数据写入新数据表即可。不用比对每条数据的每个属性项。

zhenmao
zhenmao
回复 @huan : 正解,表多加一个字段存md5值,可以将所有的md5值全查出来生成一个hash,只要有新的md5值,就直接插入就行了
huan
huan
如果没有这种id,也可以将所有字段拼接然后md5 生成一个唯一id。
0
zheng_pat
zheng_pat
现在的问题是文件中的每行转换成对象,再去数据库对比比较慢(因为需要对比50W次)。有唯一的ID判断。我也是按照你的思路就是新表和旧表。
优雅先生
优雅先生
对于文件中的每一行都请求一次数据库?
0
魔力猫
魔力猫

我建议先导入数据库,然后数据库的存储过程来完成这个比对处理工作。

你们按照这个思路试试需要多少时间。

zheng_pat
zheng_pat
不错,我试试
0
首席打酱油
首席打酱油

在别人服务器上建一个log表,用触发器记录所有需要同步的表的更新,新增,删除操作,然后每天根据log表来同步你的数据


zheng_pat
zheng_pat
别人不会提供这个
0
gvim
gvim
什么数据库?“ 属性发生了变更就更新每一条远程数据的属性是都会出现还是每一条数据都可以有一些属性不出现?比如一条数据有10个属性,每条数据必须带齐10个属性,还是可以只包含5个8个,缺的按上一次保存的默认。
gvim
gvim
回复 @zheng_pat : 当然知道数据会变更。问的是某一条数据是否带全了所有的属性域,也就是是否 可以构造出完整的 shema。
zheng_pat
zheng_pat
oracle,除了主键字段,其他属性都有可能发生变更
0
huan
huan

引用来自“huan”的答案

如果有一个ID 判断数据是否存在就比较简单了。

将50W行数据全部写入数据库,然后将原表中有的,但是新表中不存在的数据写入新数据表即可。不用比对每条数据的每个属性项。

我的意思是不用比对数据的所有属性,只用加入旧表中存在但新表中不存在的数据即可(用id判断一下),一个sql就可以搞定,而且都是批量写入操作,不用update。
0
m
moosow
数据对比方面,只要判断库里存在该数据就去更新,读取与处理用多线程,并放进队列里,另一个线程读取队列里的数据并更新到数据库里。
0
中山野鬼
中山野鬼

引用来自“mcmoo”的答案

数据对比方面,只要判断库里存在该数据就去更新,读取与处理用多线程,并放进队列里,另一个线程读取队列里的数据并更新到数据库里。
你这是个方法,不过没解决楼主,两个数据表(权且算表),之间重复数据匹配的问题。哈。这个和是否多线程没关系。我是说必要计算量。
返回顶部
顶部