V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
klgd
V2EX  ›  Python

Python 小白求助,如何快速循环百万条数据?

  •  
  •   klgd · 2018-03-14 18:04:28 +08:00 · 6738 次点击
    这是一个创建于 2476 天前的主题,其中的信息可能已经有所发展或是发生改变。

    从 mongo 里读取用户数据
    然后使用 jieba.analyse.extract_tags 进行提词
    而且是对用户的几个属性进行提词,每个属性只取部分(权重较大的)
    分词结果保存到 mongo 里

    目前问题是: 1、单个用户提词速度感觉不慢,但是百万数据就要循环好久(目前本地测试 5 万数据都要 3 小时)
    2、用户的几个属性分别提词,跟属性合并后提词,结果是否一样呢?

    请大家指教一下 我该如何优化?

    18 条回复    2018-03-15 20:20:29 +08:00
    Karblue
        1
    Karblue  
       2018-03-14 18:07:34 +08:00
    看问题是出在数据库上还是 python 上。百万数据可能是从 db 拉取到本地时间过长。如果是 python 内循环处理时间过长。可以考虑多进程或者多线程处理。如果是 DB 上的问题。就用空间换时间吧。。
    zhangsen1992
        2
    zhangsen1992  
       2018-03-14 18:16:16 +08:00
    多进程?
    CallMeHoney
        3
    CallMeHoney  
       2018-03-14 18:23:26 +08:00
    多进程 or 任务队列?
    合并后效率一样的,因为总的文本量并没有变
    regicide
        4
    regicide  
       2018-03-14 18:26:20 +08:00
    先把数据拉到内存里,然后用 pandas 操作
    klgd
        5
    klgd  
    OP
       2018-03-14 20:42:09 +08:00
    @Karblue #1 应该是内循环时间太长了 我们一次取 5 万条数据,for 循环需要 2~3 小时
    @zhangsen1992 #2 有在考虑如何实现多进程,不过新手,还在学习呢
    @CallMeHoney #3 我是想问几个属性合并后提词的结果跟每个属性提词的结果合并一样吗?
    @regicide #4 好的,我去学学 pandas 如何使用
    diggerdu
        6
    diggerdu  
       2018-03-14 20:55:16 +08:00 via iPhone
    直接 multiprocessing.mapreduce 一句话的事
    diggerdu
        7
    diggerdu  
       2018-03-14 20:55:42 +08:00 via iPhone
    @diggerdu *.map
    dd99iii
        8
    dd99iii  
       2018-03-14 21:03:46 +08:00
    multiprocessing.pool
    klgd
        9
    klgd  
    OP
       2018-03-14 22:17:18 +08:00
    @diggerdu #6
    @dd99iii #8

    指定的是用 multiprocessing.Pool 类的 map 方法吗?
    diggerdu
        10
    diggerdu  
       2018-03-15 00:43:28 +08:00 via iPhone
    @klgd 是的,这样也不用改代码
    ZoomQuiet
        11
    ZoomQuiet  
       2018-03-15 07:18:14 +08:00 via iPhone
    是也乎 ╮(╯▽╰)╭

    直觉上…这业务不用在线就地计算的吧?

    利用 mongoDB 的自动备份…将全数据…同步到另一主机…

    用管理工具…将需要的数据定期 dump 到硬盘为 .csv .json 之类文本…

    用 split 之类工具切开…

    分别 丢给多个 python 进程…

    仅将分词结果写回 mongoDB ?

    这样不占用业务响应资源…
    又最大化吞吐量…
    同时…也免去了直拉 DB 的各种问题?

    更重要的是…一切都是隔离可控的?
    nature91
        12
    nature91  
       2018-03-15 08:43:37 +08:00
    @ZoomQuiet 擦 忘记大佬叫啥了 活捉大神!!!!!
    geek123
        13
    geek123  
       2018-03-15 09:16:20 +08:00
    yumenlong
        14
    yumenlong  
       2018-03-15 14:54:25 +08:00
    感觉应该提词这比较慢,可以考虑用队列,mongo 读出数据丢到 redis 队列,然后多个消费者从队列消费提词。
    ucando
        15
    ucando  
       2018-03-15 16:39:16 +08:00
    对于第二条问题, 建议你所有属性合并后处理, 只要用分割符号(比如逗号)把属性连起来就行了, 这样分词效率要高很多.
    dd99iii
        16
    dd99iii  
       2018-03-15 18:59:26 +08:00
    @klgd 看大神的回答,不止并发的问题,也许架构上也要重新想一想
    WaterTr
        17
    WaterTr  
       2018-03-15 20:20:06 +08:00
    import multiprocessing as pro

    def work(string):
    print (string)

    if __name__ == '__main__':
    p = pro.Pool()
    with open('url.txt', encoding='utf-8') as url_list:
    for url_per in url_list:
    p.apply_async(work, args=(url_per,))
    p.close()
    p.join()

    0-0 贴一个多进程的简单例子
    WaterTr
        18
    WaterTr  
       2018-03-15 20:20:29 +08:00
    @WaterTr 缩进乱了。。。自己改一下 XD
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5648 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 03:14 · PVG 11:14 · LAX 19:14 · JFK 22:14
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.