推荐学习书目
› 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
a476286557
V2EX  ›  Python

关于 for 循环与线程~~

  •  
  •   a476286557 · Dec 12, 2018 · 3713 views
    This topic created in 2888 days ago, the information mentioned may be changed or developed.

    我现在是

    def handle_mysql(id):
        # 修改数据库的数据
        pass
    
    id_list = [...] # 里面有一百个 id
    for i in id_list:
        handle_mysql ( i )
    

    但是这样速度比较慢,然后我想用下面的方法,但是不知道是否可行

    def handle_mysql(id):
        # 修改数据库的数据
        pass
    
    id_list = [...] # 里面有一百个 id
    for i in id_list:
        线程 1,调用 handle_mysql ( i )
        线程 2,调用 handle_mysql ( i )
        线程 3,调用 handle_mysql ( i )
    
    

    请问这样可以吗?或者您有什么更好的建议能否告诉我?

    14 replies  •  2018-12-13 12:43:58 +08:00
    yosemite
    yosemite
    Dec 12, 2018
    1
    一条任务一个线程啊!有必要吗
    a476286557
    a476286557
    OP
    Dec 12, 2018
    2
    就弄两三个线程就行
    @yosemite
    Vegetable
    Vegetable
    Dec 12, 2018
    3
    multiprocessing.dummy.Pool.map
    最好是使用 aiomysql 吧
    Wisho
    Wisho
    Dec 12, 2018
    4
    把所有 id 塞到一个并发安全的队列里,然后起 N 个线程不断地从队列里取 id,执行逻辑,直到队列为空。
    Linxing
    Linxing
    Dec 12, 2018
    5
    mq?
    likuku
    likuku
    Dec 12, 2018 via iPhone
    6
    mysql 表 确认得是 innodb 的,否则锁表就慢慢等(的确当前还是有人默认用 myisam 表的)

    来个线程 /进程池 吧,自己再确保同时跑的任务不要超过 CPU 核数 /超线程数
    xpresslink
    xpresslink
    Dec 12, 2018❤️1
    7
    有一个重要的事情说三遍:
    mysql 不是线程安全的,mysql 不是线程安全的,mysql 不是线程安全的

    你如果使用多线程那么需要给每个线程创建单独的 mysql 连接。
    你同时创建过多的线程和连接最大的可能性是直接把数据库给挂死了。

    最科学的办法是按照你的 mysql 的性能创建一个连接池,可以使用 DBUtils 这个包。
    你这边多线程从连接池申请连接。
    lihongjie0209
    lihongjie0209
    Dec 12, 2018❤️1
    8
    然后你就会发现你的性能瓶颈在 mysql 上了
    largecat
    largecat
    Dec 12, 2018 via Android
    9
    用协程吧,
    chanchan
    chanchan
    Dec 12, 2018❤️1
    10
    我一般优先合并 sql,比如多条 insert into 变成一条 insert into (),(),()...
    wwqgtxx
    wwqgtxx
    Dec 13, 2018❤️1
    11
    这种事情找一个成熟 orm,人家一定有最好的优化方式在大量插入
    CRVV
    CRVV
    Dec 13, 2018
    12
    这样可行,应该会比之前快。前提是线程不共用 MySQL 的 connection,并且你的 MySQL 支持这么多的连接数

    更好的方法有
    1. 写一句 SQL 把这 100 个操作做了,大概率会快很多
    2. 不要每一句都开一个新线程,而是用一个线程池。你可以用 4 楼给的方法自己写线程池,也可以用 ThreadPoolExecutor
    3. 用 aiomysql 来并发操作数据库,这样不需要开线程,但是需要大改之前的代码

    顺便一说,“ mysql 不是线程安全的” 这句话 表义不明而且不对
    正确来说应该是,MySQL 的 driver 给你返回的 connection 不是线程安全的(也可以是线程安全的,但线程安全的 connection 没有道理,应该不会有人去写那样的代码)
    但这又是一句废话,程序里的变量几乎都不是线程安全的
    vincenttone
    vincenttone
    Dec 13, 2018
    13
    个人猜测可能提升并不大,因为目测 python 应该是用户级线程,但是操作了网络 IO,整个进程陷入内核,导致其他线程阻塞
    But,我没用过 python 进程,所以对此了解的不够全面,只凭猜测。
    建议楼主自己写出来测试一下时间(当然也期望回复一下实验结果);第二个建议是可以考虑使用 epoll 或者 select 处理这个试试;第三个建议是如果是系统线程,最好使用连接池来管理,不然容易死
    Leigg
    Leigg
    Dec 13, 2018 via iPhone
    14
    线程可以用于这种 io 型任务,但不要在线程任务多开 conn
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   669 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 44ms · UTC 23:10 · PVG 07:10 · LAX 15:10 · JFK 18:10
    ♥ Do have faith in what you're doing.