首页 新闻 会员 周边

求 C# 海量数据 挑出重复数据算法?

0
悬赏园豆:50 [已解决问题] 解决于 2010-07-21 16:21

需求: 挑出大量数据中的重复数据

.NET 做数据处理,现在是 把数据一条条addrow 到datatable里,在初始化datatable时设置其 primarykey 字段,如果是重复的数据 会引发ConstraintException,这样就能抓到重复的记录。

如何实现 对大数据量 数据 重复记录 筛选出来,有时数据量会上1000W,如果不借助datatable,自己实现,用什么样的数据结构和算法,能保证效率?如果数据量大到内存无法全部加载呢?

欢迎大家一起讨论!

问题补充: 补充: 1,该功能用于ETL 工具,加载端,数据是从一个队列中取的,不是通过SQL 查询到的。队列中的数据 是另外一个处理线程,放进去的,可能会出现脏数据。 2,ETL 加载端 要保证把队列中的数据加载到目标表,针对Oracle数据库使用Oracle 的 ODP.NET 提供的oraclebulkcopy方法,能够大大提高加载效率。但如果 在主键上 有重复记录 ,oracleBulkcopy writetoserver 方法就会报异常,并使加载目标表的索引处于不可用状态。该表就无法加载了,即使是使用insert语句。 该问题的本质: 要把流向加载端的 重复数据 过滤出来,单独写成错误数据文件。 3,现在的处理方法时,建一张datatable 只包含唯一索引字段,尝试着把过来的一行数据 唯一索引字段的值,datatable.rows.addrow(...),如果报ConstraintException异常,说明该行数据是脏数据,处理。 问题是:如果数据量特别大时,会引发outMemoryExcepiton,内存溢出。我测试(2G内存) 超过500W条,从MSDN上查到DataTable 可存储的最大行数是 16,777,216,不知道这个值是如何确定的? 和机器的内存量是否有关) 所以想 自己实现一个数据结构和算法,起到过滤器的作用,且不受数据量大小的限制,通用的,效率也是非常重要的,因为每过来一条数据都要通过这个 脏数据 过滤器。 以上两位 的方案,给我很大的启发,但还有些疑问: 1,不知道 MD5 计算信息指纹 算法 针对这样的场景是否适合,如果是1000w条数据流过来,那么就要执行1000w次 这样的计算,效率上的代价? 2,如果使用hashtable ,是使用.NET 内部的hashtabel ,或dictionary ,还是自己实现,如果使用.NET 内部的hashtable 是否有容量上线? 谢谢关注!请大家根据场景讨论
kevin@的主页 kevin@ | 初学一级 | 园豆:130
提问于:2010-07-14 09:14
< >
分享
最佳答案
0

用 MD5 计算信息指纹,然后用哈希表来消重。这是典型的消重做法,1000w 数据根本算不上海量,一台普通PC机就可以处理。

补充

MD5 计算1百万行大概是 55 秒,这是Java 的数据,.net 下你可以自己测试一下。

http://www.coderanch.com/t/203090/Performance/java/Fastest-way-calculating-MD

.net 的 Dictionary 处理 1 千万行应该还是没有问题的,我测试过。但如果再大,比如说1亿行,会有一些问题。

收获园豆:30
eaglet | 专家六级 |园豆:17139 | 2010-07-14 09:57
谢谢回答。对我有很大的启发,我使用.NET 做了测试,1000w 数据,dictionary确实没有问题。使用.NET 提供的MD5算法,求出32位的 信息指纹,对处理速度有比较大的影响。 最后做法:没有使用MD5算法,只是把主键信息组成string,放入Dictionary ,做主键重复记录 过滤。问题基本解决。现在还在测试,主要测试 并发 大数据量的处理。
kevin@ | 园豆:130 (初学一级) | 2010-07-19 14:52
@kevin@: 我测了一下,MD5 计算100万条记录大概是30秒左右,.net 带的那个是128位的,不是你说的32位的。
eaglet | 园豆:17139 (专家六级) | 2010-07-20 15:41
其他回答(3)
0

1、算哈希,假设数据变成128位的哈希码

2、根据128位的前16位分文件存储

3、每个文件里再找重复

 

这是分治的思路,至于具体根据几位分文件,是不是要二级细分都可以修改

收获园豆:20
Gray Zhang | 园豆:17610 (专家六级) | 2010-07-14 09:47
0

顶楼上两位。

Astar | 园豆:40805 (高人七级) | 2010-07-14 10:03
0

我觉得用位图算法更简单

1、建立bitarray[num]数组,全部初始化为false

2、扫描数字,如果存在数i,就将bitarray[i]置为true

3、这样只需要扫描两次(也可以扫描一次),就可以得到其中的重复数

ilove86 | 园豆:215 (菜鸟二级) | 2010-07-16 00:18
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册