【问题标题】:Optimizing Large Number of Update Queries优化大量更新查询
【发布时间】:2012-01-18 17:37:18
【问题描述】:

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

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

有没有什么好方法可以将这些更新查询合并到一个更新中?每个用户都会收到一个独特的考试分数。我找到了一些有关如何执行此操作的链接,但我的开发人员同事告诉我,这些链接无法维护且过于复杂。他们中的大多数处理向更新查询添加案例语句(每个评分考试一个)。这是一个建议的示例:

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

我是否还有其他想法可以提高此过程的性能?谢谢!

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

【问题讨论】:

    标签: mysql sql performance optimization query-optimization


    【解决方案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);
    ....
    

    【讨论】:

    • 有趣的想法。我会试一试。它应该适用于问题很少(少于 10 个)的考试。
    【解决方案2】:

    您可以生成如下查询:

    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、截断、提交,然后从头开始。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-10-31
      • 2021-07-10
      • 2015-11-08
      • 2022-01-24
      • 2011-06-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多