关于 for 循环与线程~~

2018-12-12 15:02:59 +08:00
 a476286557

我现在是

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 )

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

2574 次点击
所在节点    Python
14 条回复
yosemite
2018-12-12 15:12:32 +08:00
一条任务一个线程啊!有必要吗
a476286557
2018-12-12 15:18:05 +08:00
就弄两三个线程就行
@yosemite
Vegetable
2018-12-12 15:18:17 +08:00
multiprocessing.dummy.Pool.map
最好是使用 aiomysql 吧
Wisho
2018-12-12 15:45:20 +08:00
把所有 id 塞到一个并发安全的队列里,然后起 N 个线程不断地从队列里取 id,执行逻辑,直到队列为空。
Linxing
2018-12-12 15:48:48 +08:00
mq?
likuku
2018-12-12 15:54:17 +08:00
mysql 表 确认得是 innodb 的,否则锁表就慢慢等(的确当前还是有人默认用 myisam 表的)

来个线程 /进程池 吧,自己再确保同时跑的任务不要超过 CPU 核数 /超线程数
xpresslink
2018-12-12 16:50:31 +08:00
有一个重要的事情说三遍:
mysql 不是线程安全的,mysql 不是线程安全的,mysql 不是线程安全的

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

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

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

顺便一说,“ mysql 不是线程安全的” 这句话 表义不明而且不对
正确来说应该是,MySQL 的 driver 给你返回的 connection 不是线程安全的(也可以是线程安全的,但线程安全的 connection 没有道理,应该不会有人去写那样的代码)
但这又是一句废话,程序里的变量几乎都不是线程安全的
vincenttone
2018-12-13 11:14:37 +08:00
个人猜测可能提升并不大,因为目测 python 应该是用户级线程,但是操作了网络 IO,整个进程陷入内核,导致其他线程阻塞
But,我没用过 python 进程,所以对此了解的不够全面,只凭猜测。
建议楼主自己写出来测试一下时间(当然也期望回复一下实验结果);第二个建议是可以考虑使用 epoll 或者 select 处理这个试试;第三个建议是如果是系统线程,最好使用连接池来管理,不然容易死
Leigg
2018-12-13 12:43:58 +08:00
线程可以用于这种 io 型任务,但不要在线程任务多开 conn

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/516895

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX