V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐工具
RoboMongo
推荐书目
50 Tips and Tricks for MongoDB Developers
Related Blogs
Snail in a Turtleneck
dtgxx
V2EX  ›  MongoDB

mongodb 导入数据怎么破

  •  
  •   dtgxx · 2020-07-29 20:55:25 +08:00 · 6477 次点击
    这是一个创建于 1585 天前的主题,其中的信息可能已经有所发展或是发生改变。

    数据量太大 几百亿,但是只有一台机器,存储够用。


    数据需要以三个字段建联合唯一索引。


    如果不建索引,导入差不多一周就完事了。 但是联合唯一索引在导入数据之后有重复数据就无法创建了,去掉重复数据也非常的难。 建索引之后再导数据,非常非常非常的慢,可能是索引影响了插入速度。。


    大佬们有啥高招吗

    34 条回复    2020-08-08 15:16:43 +08:00
    wupher
        1
    wupher  
       2020-07-29 21:01:54 +08:00
    那就不要用唯一性索引
    dtgxx
        2
    dtgxx  
    OP
       2020-07-29 22:23:23 +08:00
    @wupher #1 尴尬。。。这个是刚需。。
    abcbuzhiming
        3
    abcbuzhiming  
       2020-07-29 22:29:24 +08:00
    不能自己写程序读取数据,然后在去重的基础上导入吗?无非就是慢一点呗
    dtgxx
        4
    dtgxx  
    OP
       2020-07-29 22:33:19 +08:00
    @abcbuzhiming #3 写了很多程序,也做了非常多的优化,慢的不行。。数据量太大,程序无法支持去重的。
    jiangzhuo
        5
    jiangzhuo  
       2020-07-29 22:37:47 +08:00   ❤️ 1
    去阿里云 AWS 之类的开一套高性能的机器,导入,然后关闭数据库,把导入好的文件传回你那台机器,用导好的文件启动数据库。
    dtgxx
        6
    dtgxx  
    OP
       2020-07-29 22:40:05 +08:00
    @jiangzhuo #5 你这个建议蛮不错的,以后遇到需求感觉可以这么试试,挺好。只是目前这部分数据价格比较高买的,不太想放到别人服务器。
    594duck
        7
    594duck  
       2020-07-29 23:08:48 +08:00 via iPhone
    就不能先倒入关系数据库,再处理好所有的逻辑。死磕那个干嘛
    billlee
        8
    billlee  
       2020-07-29 23:23:23 +08:00
    你导进去要干嘛?这样即使能导完用起来还是会很慢啊
    dtgxx
        9
    dtgxx  
    OP
       2020-07-30 00:04:39 +08:00
    @billlee #8 查询用,之前不加联合索引是查询是很快的,两百亿数据查询,差不多 50ms 就能返回。
    dtgxx
        10
    dtgxx  
    OP
       2020-07-30 00:06:13 +08:00
    @594duck #7 主要是目前只有一个机器,用关系型数据库会比 mongo 慢更多。mongo 不用联合索引每秒我这可以处理到大约 50 万条数据,关系型数据库单点的肯定做不到。
    zxlzy
        11
    zxlzy  
       2020-07-30 01:01:23 +08:00 via Android
    @dtgxx 他这个建议是最靠谱的了,至于数据价格贵…… 多少大中小互联网公司生死存亡的数据都放在阿里云和 aws 上了。
    entertainyou
        12
    entertainyou  
       2020-07-30 03:36:07 +08:00 via Android
    分表?
    594duck
        13
    594duck  
       2020-07-30 04:33:49 +08:00 via iPhone
    @dtgxx 200 亿 50ms 返回?纯文本文件 200 亿行,grep 一下中间的文件,50ms 都回不了。

    要么你这技术已经很到家了,要么我淘汰了
    showhand
        14
    showhand  
       2020-07-30 06:51:34 +08:00 via iPhone
    是不是先读取索引数据,把重复的记下来,然后导入的时候判断下数据是否在重复的索引里面
    wupher
        15
    wupher  
       2020-07-30 09:16:26 +08:00
    索引无非是为了方便查询,你可以在查询函数上做文章,查询多条记录后,再返回你想要的唯一记录,或者通过逻辑字段来标识删除,都是可以的。

    唯一性索引本来就很影响性能,数据,建议谨慎使用。几百亿数据,正常都应该 sharding 了,更不建议使用唯一性索引。

    5 楼的建议也相当棒,买机器来处理也是条思路。
    dtgxx
        16
    dtgxx  
    OP
       2020-07-30 09:25:23 +08:00
    @zxlzy #11 放阿里云 aws 基本都是民口的。
    JCZ2MkKb5S8ZX9pq
        17
    JCZ2MkKb5S8ZX9pq  
       2020-07-30 09:26:43 +08:00
    需求没看很懂,唯一索引是建一个单独的字段,还是 createIndex ?
    如果碰到重复,处理逻辑是什么样的?

    另外有个比较基本的差别,insert_many 比逐条插入要快很多。可以考虑先 createIndex 然后批量导入,最后再说处理重复,不知道能不能行。
    dtgxx
        18
    dtgxx  
    OP
       2020-07-30 09:27:21 +08:00
    @wupher #15 确实是,感觉之前的不使用索引的方式也可以,只是下游取的时候得自己做去重了,而且增量订阅的时候,每次更新的数据量也越来越大了。
    dtgxx
        19
    dtgxx  
    OP
       2020-07-30 09:28:52 +08:00
    @JCZ2MkKb5S8ZX9pq #17 三个字段的联合索引,目前使用 mongoinsert 导入数据,insert_one 和 insert_many 都比较慢,都放弃了。重复数据保留任何一条就可以了。
    zhuifeng1017
        20
    zhuifeng1017  
       2020-07-30 09:37:54 +08:00 via Android
    用 mongoimport 导入 csv 或 tsv,重复数据会自动跳过的
    dtgxx
        21
    dtgxx  
    OP
       2020-07-30 09:46:05 +08:00
    @zhuifeng1017 #20 啊 大佬,这个哪里有说明吗,真是这样就太好啦
    JCZ2MkKb5S8ZX9pq
        22
    JCZ2MkKb5S8ZX9pq  
       2020-07-30 09:57:14 +08:00
    @dtgxx 20 楼说的看了眼,学到了。但感觉不管哪种去重,查找的花销总归是难免的,不如先全部丢进去再说了。可以以后慢慢处理。

    > 但是联合唯一索引在导入数据之后有重复数据就无法创建了
    这个没有看懂,如果是 mongo 自带的 index 不是可以重复的吗?
    windyland
        23
    windyland  
       2020-07-30 10:00:26 +08:00 via Android
    所以为什么不试试阿里云开内存盘呢。。。。。。?
    dtgxx
        24
    dtgxx  
    OP
       2020-07-30 10:02:45 +08:00
    @JCZ2MkKb5S8ZX9pq #22 先导入数据,然后添加唯一索引,被索引的字段如果有重复,这个索引就会建失败。
    JCZ2MkKb5S8ZX9pq
        25
    JCZ2MkKb5S8ZX9pq  
       2020-07-30 10:14:04 +08:00
    @dtgxx 是用

    createIndex({name:1,gender:1,age:1})
    如果是这种是可以重复的吧?

    加了{unique: true}的话倒不清楚,没用过这个,查询会更快吗?
    我去试试看这个。

    也可以考虑初期先导入,用起来再说,日后慢慢去重做 unique 吧。
    dtgxx
        26
    dtgxx  
    OP
       2020-07-30 10:16:50 +08:00
    @JCZ2MkKb5S8ZX9pq #25 联合唯一索引,唯一指的就是 unique 。
    JCZ2MkKb5S8ZX9pq
        27
    JCZ2MkKb5S8ZX9pq  
       2020-07-30 10:32:27 +08:00   ❤️ 1
    @dtgxx 嗯,看了下的确没有先 compound 然后再转换的方法。那就等于全部数据要预处理,那是怎么都快不起来了。
    去重的话感觉也是先建非 unique 的 index,然后排序去重能快一点。不过你这个量是满夸张的。
    wupher
        28
    wupher  
       2020-07-30 11:08:55 +08:00   ❤️ 1
    只有单条重复性不多的情况可以用这种方法。

    如果单条数据重复数量级很大,那就不适合了。

    几百亿也可以考虑放 ES 或者 Cassandra
    dtgxx
        29
    dtgxx  
    OP
       2020-07-30 15:37:27 +08:00
    @zhuifeng1017 #20
    引用:用 mongoimport 导入 csv 或 tsv,重复数据会自动跳过的
    这个你自己试过吗?我刚测试了,并不可以。

    @wupher 是 之前考虑用分布式大数据存储之类的,最终机器限制,就没搞。
    joApioVVx4M4X6Rf
        30
    joApioVVx4M4X6Rf  
       2020-07-30 18:07:53 +08:00
    假设数据有 500 亿。
    首先对数据对三个联合主键做一个取余,假设是模 10000,这样数据被分成了 10000 份,平均每份 500w 数据,所以只需要对这 500w 数据去重就行了,做好后直接插入数据库,不用建立唯一索引
    smallgoogle
        31
    smallgoogle  
       2020-07-30 18:36:35 +08:00
    哎。别说了。才弄完。5 亿数据。
    dtgxx
        32
    dtgxx  
    OP
       2020-07-30 18:43:17 +08:00
    @v2exblog #30 没太明白,把数据分成 1 万份,不也需要每一份都去重吗。
    @smallgoogle 共勉老铁。
    kuafou
        33
    kuafou  
       2020-08-08 14:36:27 +08:00
    @dtgxx 问题解决了吗?
    dtgxx
        34
    dtgxx  
    OP
       2020-08-08 15:16:43 +08:00
    @kuafou #33 只能导入之后,去重,再建索引,去重也非常慢,不过目前没有别的好办法。去重虽然慢,但是要远远快于提前建好索引的情况。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2716 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 07:44 · PVG 15:44 · LAX 23:44 · JFK 02:44
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.