优化大量更新查询

时间:2012-01-18 17:37:19

标签: mysql sql performance optimization query-optimization

我有一个应用程序,用户开始参加测试,有时用户忘记完成/提交他们的测试。管理员已经请求了一个按钮,他们可以点击该按钮进入系统,查找所有未提交的考试,并对其进行评分。

此过程使用单个select语句完成,以加载所有受影响的考试。然后,内存中进程确定每个用户的分数。问题是用每个用户的分数更新数据库非常慢。更新查询需要几分钟,并且运行数百或数千个更新语句(取决于等待处理的未提交的检查数)。我的数据库服务器使用MySQL。

有没有什么好方法可以将这些更新查询合并到一个更新中?每个用户都会收到他们考试的唯一分数。我找到了一些关于如何做到这一点的链接,但我的开发人员告诉我,这些都是不可维护的,而且太复杂了。其中大部分涉及向更新查询添加案例陈述(每个评分考试一个)。以下是一个建议的示例:

http://dashasalo.com/2009/06/18/update-multiple-rows-with-different-values/

我是否还有其他想法可能会改善此流程的效果?谢谢!

注意:我确实在此表上设置了正确的索引,每个单独的查询需要0.2-0.5秒才能完成。我还建议夜间cron工作或自动清理。管理员拒绝了这一说法,他们想要控制清理过程何时发生,并且他们不接受任何cron /自动/夜间进程。

2 个答案:

答案 0 :(得分:1)

当你说评分在内存中完成时,我认为你的意思是应用程序正在从数据库中选择测试答案并对其进行评分。

确定分数后,您可以根据分数对结果进行排序,并为每个分数构建测试列表。使用此列表,您可以构建一些动态SQL来更新具有相同分数的所有测试,例如:

UPDATE tests
SET score = 100
WHERE TestID IN (1,2,10,1000);

UPDATE tests
SET score = 99
WHERE TestID IN (8,12,46,2000);
....

答案 1 :(得分:0)

您可以生成如下查询:

UPDATE targettable tt
JOIN (SELECT 1 as user_id, 100 as score
  UNION ALL
  SELECT 2 as user_id, 150 as score) st
USING (user_id)
SET tt.score = st.score

子选择可能是几百行的UNION。或者,您可以创建一个临时表,填充数据子集,进行类似的JOIN,截断,提交,并从头开始。