PHP 脚本要对 600 万行的 mysql 进行一次批处理操作,怎样才能用多个进程达到最快执行? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
alwayshere
V2EX    程序员

PHP 脚本要对 600 万行的 mysql 进行一次批处理操作,怎样才能用多个进程达到最快执行?

  •  
  •   alwayshere 2018-08-06 14:10:34 +08:00 5382 次点击
    这是一个创建于 2626 天前的主题,其中的信息可能已经有所发展或是发生改变。

    要扫描一次全表,php 对每一行都要批处理一次,如果单个 php 进程把 600 万行载入内存扫描一次全表处理实在太慢,想用多个 php 进程来扫描表:

    1. 想用多个 php 进程从 MySQL 中随机取出一些行出来,因为 primary id 不连续,但用 MySQL 的 ORDER BY RAND()慢的令人发指

    2. 想快一点也只能用两个 php 进程,一个 ORDER BY id ASC 顺序执行,一个 ORDERY BY id DESC 倒序执行,但两个进程还是太慢

    估计表述得不太明白,反正就是怎样能将 mysql 快速截取成一段一段的行,让多个 php 进程去执行?

    33 条回复    2018-08-07 14:55:33 +08:00
    Sornets
        1
    Sornets  
       2018-08-06 14:14:29 +08:00
    一个思路:
    记录 id 取余,比如十个进程,就对 10 取余,根据余数查找对应 id,proc_id = rec_id % 10,
    z550665887
        2
    z550665887  
       2018-08-06 14:18:04 +08:00
    limit ?
    582033
        3
    582033  
       2018-08-06 14:25:58 +08:00
    分页
    Rekkles
        4
    Rekkles  
       2018-08-06 14:29:36 +08:00
    PHP 哪有什么多进程 pthread 性能不会有太大的提高 这种东西如果打算用 PHP 做,mysql 和内存 能扛就能做,一次取 1k 条数据(内存够就多取点),处理 ,update,循环
    lihongjie0209
        5
    lihongjie0209  
       2018-08-06 14:30:57 +08:00
    生产者消费者喽
    widdy
        6
    widdy  
       2018-08-06 14:34:20 +08:00   2
    有这扯淡时间,一个脚本 600w 行早跑完了,为啥不一次取个 1w 条。
    nsxuan
        7
    nsxuan  
       2018-08-06 15:00:43 +08:00
    关键是要开启事务
    colincat
        8
    colincat  
       2018-08-06 15:46:00 +08:00
    @widdy 说的没毛病
    newtype0092
        9
    newtype0092  
       2018-08-06 15:54:15 +08:00
    @widdy 那就来讨论下 6 亿条怎么做嘛,让这个淡扯的有点意义~
    tanszhe
        10
    tanszhe  
       2018-08-06 15:58:00 +08:00
    这种简单到爆的问题 就不要来问了
    mumbler
        11
    mumbler  
       2018-08-06 16:02:37 +08:00
    order by id limit 1,10000
    order by id limit 10001,10000
    order by id limit 20001,10000
    order by id limit 30001,10000
    这样就可以一万一万读了,和分页一样
    widdy
        12
    widdy  
       2018-08-06 16:03:09 +08:00
    @newtype0092 , 真这么大,时间来最清晰,php xxoo.php 2017-01 , php xxoo.php 2017-02 ...
    ps1aniuge
        13
    ps1aniuge  
       2018-08-06 16:06:41 +08:00
    一个进程不行,就多个进程。多个进程不行就 n 机子分布。
    这里面要有一个队列,分发任务或表 id。根据实际情况,一次分发一百,一千,一万。
    vovov
        14
    vovov  
       2018-08-06 16:10:00 +08:00 via Android
    用队列,随便多少条都可以
    GGGG430
        15
    GGGG430  
       2018-08-06 16:10:42 +08:00 via iPhone
    pcntl,我上周才刚用过,你把行数除以进程数,然后把各个起始 id 传给各个子进程,快的一比
    yuanfnadi
        16
    yuanfnadi  
       2018-08-06 16:11:33 +08:00
    select * from xxx where id > 0 limit 1000
    然后取最后一个 ID 为 1022
    select * from xxx where id > 1022 limit 1000
    想开几个线程都可以。
    GGGG430
        17
    GGGG430  
       2018-08-06 16:13:12 +08:00 via iPhone
    不要排序,各个进程处理各自起始 id 部门数据,然后各个进程都每次取 100 条数据作为一个事物提交,但注意 mysql 连接数和执行脚本机器的负载
    dobelee
        18
    dobelee  
       2018-08-06 16:16:20 +08:00 via Android
    600w。。随便跑跑就行,等你写好算法逻辑,10 遍都跑完了。
    jswh
        19
    jswh  
       2018-08-06 16:32:51 +08:00
    记得别用对象,用数组就行
    InternetExplorer
        20
    InternetExplorer  
       2018-08-06 16:38:31 +08:00
    能不能直接用 sql 处理?
    xmadi
        21
    xmadi  
       2018-08-06 18:11:39 +08:00 via iPhone
    用 limit 效率很低 可以直接先人工查询最大的 id 和最小的 id 然后以十万个 id 间隔分组 很粗糙肯定不均匀但是没有影响 开进程池 每个进程用 where 筛选分组数据进行处理
    bugsnail
        22
    bugsnail  
       2018-08-06 19:39:48 +08:00 via iPhone
    @mumbler https://oyifan.com/2016/03/23/offsetSlow/

    了解一下,limit 是会越来越慢的
    singer
        23
    singer  
       2018-08-06 19:47:37 +08:00 via iPhone
    id 放到 redis 的 list,然后多进程拉起来就好了个
    xschaoya
        24
    xschaoya  
       2018-08-06 21:41:24 +08:00
    最简单的多进程资源分配啊,简单粗暴的就是主键分段开多进程。高级点的可以用消息队里(生产者消费者类模型)
    GreatHumorist
        25
    GreatHumorist  
       2018-08-06 22:38:01 +08:00 via iPhone
    还是想想直接用 sql 吧,php 弄很麻烦,上周末弄过一个三百万行的匹配,php 遍历到十万左右就很慢了。最后直接用 sql,贼快,加起来不超过 10 分钟
    yangqi
        26
    yangqi  
       2018-08-06 22:41:32 +08:00
    多复杂的处理不能在 mysql 里面完成?
    beastk
        27
    beastk  
       2018-08-06 22:45:55 +08:00 via iPhone
    要不就用 php 执行个 go 或者 python,分分钟给你跑完
    jsjscool
        28
    jsjscool  
       2018-08-06 23:46:11 +08:00
    使用进程间通信也是几句代码的事情。和语言无关,通信的方式无非就是信号量,消息队列,管道这几种,都是操作系统提供的。选择一种自己能理解的方式就行了,代码都贴给你
    http://blog.it2048.cn/article-php-thread/

    PS:600 万行这么少的数据,几句代码就能搞定,用啥多线程。 就算用了多线程速度也提升不了多少,MySQL 的硬盘 IO 会是瓶颈。比如每秒 40M,你写入数据的极限也差不多是 40M/s。
    wizardoz
        29
    wizardoz  
       2018-08-07 10:30:33 +08:00
    为啥要用 php 处理?不是放进数据库用 SQL 处理最快吗?
    allgy
        30
    allgy  
       2018-08-07 10:54:46 +08:00
    @jsjscool @alwayshere php 的线程就是个废物不建议使用,大数据量用存储过程就行
    slince
        31
    slince  
       2018-08-07 12:33:32 +08:00
    这种问题应该要你们的 dba,为啥要程序员自己写脚本去解决
    batter
        32
    batter  
       2018-08-07 14:30:58 +08:00
    说 limit 的,你是来搞笑的么,,,,,对于超大数据来说,limit 效率非常的低,既然按照 id 处理,按照 id>$id 应该会好点吧
    abccccabc
        33
    abccccabc  
       2018-08-07 14:55:33 +08:00
    楼主,你还没有执行吗?队列呀,14 楼,23 楼都说了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5336 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 09:25 PVG 17:25 LAX 02:25 JFK 05:25
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86