Pythonマルチプロセス並列実行によるMySQLバッチUPDATE実行速度の高速化


テーブルtがあります
mysql> desc t;
+----------------+--------------+------+-----+---------+----------------+
| Field          | Type         | Null | Key | Default | Extra          |
+----------------+--------------+------+-----+---------+----------------+
| owner          | varchar(30)  | YES  |     | NULL    |                |
| object_name    | varchar(128) | YES  |     | NULL    |                |
| subobject_name | varchar(30)  | YES  |     | NULL    |                |
| object_id      | int          | NO   | PRI | NULL    | auto_increment |
| data_object_id | int          | YES  |     | NULL    |                |
| object_type    | varchar(19)  | YES  |     | NULL    |                |
| created        | datetime     | YES  |     | NULL    |                |
| last_ddl_time  | datetime     | YES  |     | NULL    |                |
| timestamp      | varchar(19)  | YES  |     | NULL    |                |
| status         | varchar(7)   | YES  |     | NULL    |                |
| temporary      | varchar(1)   | YES  |     | NULL    |                |
| generate       | varchar(1)   | YES  |     | NULL    |                |
| secondary      | varchar(1)   | YES  |     | NULL    |                |
| namespace      | int          | YES  |     | NULL    |                |
| edition_name   | varchar(30)  | YES  |     | NULL    |                |
+----------------+--------------+------+-----+---------+----------------+
15 rows in set (0.00 sec)

全部で116 w行のデータがあります
mysql> select count(*) from t;
+----------+
| count(*) |
+----------+
|  1167136 |
+----------+
1 row in set (0.17 sec)

update t set owner='SB'を実行したい.
必ず直接上のSQLに走ることができなくて、その1つ、これは1つの大きい事務で、主従の遅延を招くことができて、次に、SQLはwhereのフィルタリングの条件がなくて、全体の表をロックします
MySQLは、プライマリ・キー・スライスを使用して、上のSQLをスライスできます.https://blog.csdn.net/robinson1988/article/details/106007292
テーブルをプライマリ・キーに従ってスライスした後、データを複数に分割し、複数のウィンドウを開いて並列に実行することで、UPDATEの実行速度を速めることができます.
以下はPython全自動メインキースライス+並列実行スクリプトです.スクリプトにはデータを4点に分割し、4つの並列プロセスを開きます.
from multiprocessing import Pool
import pymysql
import time
import os
import io

def processData(txt):
 print('    :', time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
 command='mysql -uroot -poracle -Dtest ',avg_row * (n - 1),' and object_id<=', avg_row * n, ';') split_sql " \
       "FROM (SELECT n, min_id, max_id, ceil(max_id / 100) avg_row FROM (WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT n + 1  FROM x  WHERE n < 100" \
       ") SELECT *  FROM x) a, (SELECT min(object_id) min_id FROM t) b, (SELECT max(object_id) max_id  FROM t) c ) a"
 cur.execute(sql)
 rows = []
 result = cur.fetchall()
 slice0 = open('slice0.txt', 'w', newline='', encoding='utf8')
 slice1 = open('slice1.txt', 'w', newline='', encoding='utf8')
 slice2 = open('slice2.txt', 'w', newline='', encoding='utf8')
 slice3 = open('slice3.txt', 'w', newline='', encoding='utf8')
 for i in range(1,len(result)+1):
  if i%4==0:
     slice0.writelines(result[i - 1][0] + '
') elif i%4==1: slice1.writelines(result[i - 1][0] + '
') elif i%4==2: slice2.writelines(result[i - 1][0] + '
') elif i%4==3: slice3.writelines(result[i - 1][0] + '
') slice0.close() slice1.close() slice2.close() slice3.close() cur.close() conn.close() with Pool(4) as pool: pool.map(processData,['slice0.txt','slice1.txt','slice2.txt','slice3.txt'])

1つのウィンドウを走る:
mysql> update t set owner='NC';
Query OK, 1167136 rows affected (40.34 sec)
Rows matched: 1167136  Changed: 1167136  Warnings: 0

プライマリ・キーに従ってスライスして並行して走ります.
[root@server ~]# python3 update.py
    : 2020-05-29 15:53:38
    : 2020-05-29 15:53:38
    : 2020-05-29 15:53:38
    : 2020-05-29 15:53:38
mysql: [Warning] Using a password on the command line interface can be insecure.
mysql: [Warning] Using a password on the command line interface can be insecure.
mysql: [Warning] Using a password on the command line interface can be insecure.
mysql: [Warning] Using a password on the command line interface can be insecure.
    : 2020-05-29 15:53:49
    : 2020-05-29 15:53:49
    : 2020-05-29 15:53:49
    : 2020-05-29 15:53:50

4つの並列プロセスを開くことができ、全部で10秒で走り終わり、単一ウィンドウで40秒で4倍の性能を向上させることができます.
最後に、どのくらいの並列プロセスを開くかはあなたのマシンCPUと関係があります.CPU COREを超える並列プロセスはお勧めしません.