所以我有一个python脚本,它通过大约350,000个数据对象,并且根据一些测试,它需要更新一行代表MySQl数据库中每个对象。我也使用pymysql,因为我在使用它时遇到的麻烦最少,尤其是在发送大量选择查询时(select where column IN (....)
子句包含可能包含100,000多个值的语句)。
由于每行的每次更新都可能不同,因此每个更新语句都不同。例如,对于一行,我们可能希望更新first_name
,但对于另一行,我们希望保持first_name
不变,我们希望更新last_name
。
这就是为什么我不想使用接受一个通用更新语句的cursor.executemany()
方法,然后你给它提供值,但正如我所提到的,每个更新都是不同的,所以有一个通用的更新声明并不适合我的情况。我也不想通过网络单独发送超过350,000个更新语句。无论如何,我可以将所有更新语句打包在一起并立即发送它们吗?
我尝试在一个查询中使用cursor.execute()
方法,但它似乎不会更新所有行。
答案 0 :(得分:5)
如果您可以对您的"测试进行编码,那么您的最佳表现就是"进入SQL逻辑本身,所以你可以把所有东西都归结为少数UPDATE语句。或者至少以这种方式尽可能多地完成,以便需要单独更新更少的行。
例如:
UPDATE tablename set firstname = [some logic]
WHERE [logic that identifies which rows need the firstname updated];
您对测试的描述并不多,所以很难确定。但是你通常可以通过一些工作在你的WHERE子句中获得相当多的逻辑。
另一个选择是将您的逻辑放入存储过程。您仍然会进行350,000次更新,但至少他们并不是所有人都会通过电话进行更新#34;。不过,我会把它作为最后的手段。业务逻辑应尽可能保留在应用程序层中,并且存储过程使您的应用程序不那么便携。
答案 1 :(得分:4)
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跳入'答案'而不仅仅是'评论',他应该得到'赏金'。)