我正在研究使用单个查询一次更新多行的最佳方法。 目前我有:
UPDATE `profiles` SET `name` = CASE `id` WHEN 1 THEN 'John' WHEN 2 THEN 'Jane' END, `gender` = CASE `id` WHEN 1 THEN 'Male' WHEN 2 THEN 'Female' END WHERE `id`=1 OR `id`=2
但是这需要大约4分钟才能完成(我的真实查询是在一个包含2000万行的数据库中的10个字段),而不是需要大约1秒钟的单个更新查询。
我想弄清楚为什么,实际发生了什么?我认为通过在WHERE子句中指定id可以加快它的速度。
答案 0 :(得分:0)
你有id的索引吗?如果没有,最好创建一个(警告,这可能需要很长时间,在非高峰时段执行此操作):
CREATE INDEX id_idx ON profiles (id);
顺便说一下,对表中有2000万行的10个字段的查询可能需要很长时间,特别是如果没有索引或缓存是冷的话。
更新:为了测试,因为我很好奇,我试图重现你的情况。为此我编写了一些测试数据。
DDL:https://gist.github.com/b76ab1c1a9d0ea071965
更新查询:https://gist.github.com/a8841731cb9aa5d8aa26
用测试数据填充表的Perl脚本:https://gist.github.com/958de0d848c01090cb9d
但是,正如我在下面的评论中已经提到的,Mysql将阻止您插入重复数据,因为id是您的PRIMARY KEY,但不是唯一的。如果您可以对表架构发表评论和/或发布您的DDL,这将有很大帮助。
祝你好运! 亚历克斯。答案 1 :(得分:0)
你能为个人资料表发布DDL吗?这将有助于查看您设置了哪种索引(例如 - 我们可以假设id列是主键吗?)。如果你正在使用MySQL,那么只需运行'SHOW CREATE TABLE profiles'来生成DDL。
有几点可能会有所帮助:
1)尝试在WHERE子句中使用BETWEEN而不是OR。例如
更新profiles
SET `name` =
CASE `id` WHEN 1 THEN 'John'
WHEN 2 THEN 'Jane' END,
`gender` = CASE `id`
WHEN 1 THEN 'Male' WHEN 2 THEN 'Female' END
WHERE `id` between 1 and 2;
2)尝试在单独的查询中拆分查询,以避免使用CASE语句,例如
update `profiles`
set `name` = 'John',
`gender` = 'Male'
where `id` = 1;
和
update `profiles`
set `name` = 'Jane',
`gender` = 'Female'
where `id` = 2;
我不知道这是否可行,因为我不确定你在什么情况下使用查询!希望有所帮助。
答案 2 :(得分:0)
您可以为所有字段指定所有案例,因此我们有更好的想法。如果您有仅针对id = 1和2进行更新的修复案例,则将查询拆分为2个查询,如:
update `profiles` set `name` = 'John', `gender` = 'Male' where `id` = 1;
update `profiles` set `name` = 'Jane', `gender` = 'Female' where `id` = 2;