PyMySQL 一次查询中的不同更新?
PyMySQL different updates in one query?
所以我有一个 python 脚本,它遍历大约 350,000 个数据对象,并且根据一些测试,它需要更新代表 MySQl 数据库中的每个对象的行.我也在使用 pymysql,因为我用它遇到的麻烦最少,尤其是在发送大型 select 查询时(select 带有 where column IN (....)
子句的语句可以包含 100,000+ 个值)。
由于每行的每次更新都可以不同,因此每个更新语句都是不同的。例如,对于一行,我们可能希望更新 first_name
,但对于另一行,我们希望保持 first_name
不变,我们希望更新 last_name
.
这就是为什么我不想使用 cursor.executemany()
方法,该方法接受一个通用更新语句,然后您将值提供给它,但是正如我提到的,每个更新都是不同的,因此只有一个通用更新声明并不真正适用于我的情况。我也不想通过网络单独发送超过 350,000 条更新语句。无论如何,我可以将所有更新语句打包在一起并立即发送吗?
我尝试将它们全部放在一个查询中并使用 cursor.execute()
方法,但它似乎没有更新所有行。
SQL #1: CREATE TABLE t
包含您可能需要更改的任何列。使它们全部 NULL
(而不是 NOT NULL
)。
SQL #2:对所有需要的更改进行批量 INSERT
(或 LOAD DATA
)。例如,如果仅更改 first_name
,则填写 id
和 first_name
,但其他列为 NULL
.
SQL#3-14:
UPDATE real_table
JOIN t ON t.id = real_table.id
SET real_table.first_name = t.first_name
WHERE t.first_name IS NOT NULL;
# ditto for each other column.
除#1 外的所有 SQL 都将耗时。而且,由于 UPDATE
需要构建撤消日志,它可能会超时或出现其他问题。如有必要,请参阅 a discussion of chunking。
如有必要,使用COALESCE()
、GREATEST()
、IFNULL()
等函数
质量UPDATEs
通常意味着架构设计不佳。
(如果 Ryan 使用 'Answer' 而不是 'Comment',他可能应该得到 'bounty'。)
如果您可以将 "tests" 编码到 SQL 逻辑本身,那么您的最佳表现将是,这样您就可以将所有内容归结为少量的 UPDATE 语句。或者至少以这种方式完成尽可能多的工作,这样需要单独更新的行就更少了。
例如:
UPDATE tablename set firstname = [some logic]
WHERE [logic that identifies which rows need the firstname updated];
您对测试的描述不多,所以很难确定。但是您通常可以通过一些工作在您的 WHERE 子句中获得相当多的逻辑。
另一种选择是将您的逻辑放入存储过程中。您仍将进行 350,000 次更新,但至少它们不是全部 "going over the wire"。不过,我只会将其用作最后的手段;业务逻辑应尽可能保留在应用层,而存储过程会使您的应用程序的可移植性降低。
所以我有一个 python 脚本,它遍历大约 350,000 个数据对象,并且根据一些测试,它需要更新代表 MySQl 数据库中的每个对象的行.我也在使用 pymysql,因为我用它遇到的麻烦最少,尤其是在发送大型 select 查询时(select 带有 where column IN (....)
子句的语句可以包含 100,000+ 个值)。
由于每行的每次更新都可以不同,因此每个更新语句都是不同的。例如,对于一行,我们可能希望更新 first_name
,但对于另一行,我们希望保持 first_name
不变,我们希望更新 last_name
.
这就是为什么我不想使用 cursor.executemany()
方法,该方法接受一个通用更新语句,然后您将值提供给它,但是正如我提到的,每个更新都是不同的,因此只有一个通用更新声明并不真正适用于我的情况。我也不想通过网络单独发送超过 350,000 条更新语句。无论如何,我可以将所有更新语句打包在一起并立即发送吗?
我尝试将它们全部放在一个查询中并使用 cursor.execute()
方法,但它似乎没有更新所有行。
SQL #1: CREATE TABLE t
包含您可能需要更改的任何列。使它们全部 NULL
(而不是 NOT NULL
)。
SQL #2:对所有需要的更改进行批量 INSERT
(或 LOAD DATA
)。例如,如果仅更改 first_name
,则填写 id
和 first_name
,但其他列为 NULL
.
SQL#3-14:
UPDATE real_table
JOIN t ON t.id = real_table.id
SET real_table.first_name = t.first_name
WHERE t.first_name IS NOT NULL;
# ditto for each other column.
除#1 外的所有 SQL 都将耗时。而且,由于 UPDATE
需要构建撤消日志,它可能会超时或出现其他问题。如有必要,请参阅 a discussion of chunking。
如有必要,使用COALESCE()
、GREATEST()
、IFNULL()
等函数
质量UPDATEs
通常意味着架构设计不佳。
(如果 Ryan 使用 'Answer' 而不是 'Comment',他可能应该得到 'bounty'。)
如果您可以将 "tests" 编码到 SQL 逻辑本身,那么您的最佳表现将是,这样您就可以将所有内容归结为少量的 UPDATE 语句。或者至少以这种方式完成尽可能多的工作,这样需要单独更新的行就更少了。
例如:
UPDATE tablename set firstname = [some logic]
WHERE [logic that identifies which rows need the firstname updated];
您对测试的描述不多,所以很难确定。但是您通常可以通过一些工作在您的 WHERE 子句中获得相当多的逻辑。
另一种选择是将您的逻辑放入存储过程中。您仍将进行 350,000 次更新,但至少它们不是全部 "going over the wire"。不过,我只会将其用作最后的手段;业务逻辑应尽可能保留在应用层,而存储过程会使您的应用程序的可移植性降低。