【问题标题】:MySQL update with subselect too slowMySQL 用 subselect 更新太慢
【发布时间】:2011-09-07 02:47:21
【问题描述】:

有一个更新查询需要超过 20 分钟的问题(我在那之后杀死了它)。

场景:

表一有大约 30 万条记录。

表二包含相同的记录集(已复制),但有一个额外的字段,该字段需要包含与多个字段匹配的记录的 id,并且具有另一个字段的最高值(分数)。澄清一下,最终结果应该是包含 30 万条记录的表 2,每条记录的 id 都是具有相同基本属性集的另一条记录,以及具有这些属性的记录集中的最高分。

当我只将 2K 记录而不是完整的 300k 记录复制到表 2 中时,以下内容在 ~5 秒内完成。

UPDATE vtable2 v1 SET v1.buddy = (
    SELECT v2.id FROM vtable1 v2
    WHERE
    v2.group_id = v1.group_id AND
    // 6 more basic comparisons
    ORDER BY score DESC LIMIT 1
)

我需要为完整的 300K 记录寻找伙伴。加入和排序所涉及的所有字段都有索引。

非常感谢您的帮助。

【问题讨论】:

  • 添加当前需要 20 分钟的查询怎么样?这里没有太多事情要做。
  • 我唯一的建议是进行比较,或者缺少它们的索引,或者对字段进行错误计算,例如,而不是将 -7 作为常数添加到当前日期,添加 7到字段中的每个日期,诸如此类的事情
  • @tloach:这是需要 20 分钟的查询。

标签: mysql performance greatest-n-per-group sql-update


【解决方案1】:

MySQL 子查询往往要慢一些。在这种情况下,我更喜欢使用连接。我不太清楚你的架构设计——但你可以尝试这样的事情——

UPDATE vtable2 v1
[INNER] JOIN vtable1 v2 
ON v2.group_id = v1.group_id
AND //OTHER JOIN CONDITIONS IF ANY
WHERE
//any other conditions
SET
v1.buddy = v2.id

PS - 当然,您需要确保列上有正确的索引。如果您需要这方面的帮助,您可以发布带有解释计划的整个查询。

【讨论】:

  • 我考虑过这个,但在分数栏中没有看到如何工作。
  • 不太清楚您的分数问题,您能否发布表格列并举例说明如何计算或选择分数?
  • 分数是表一中的一列。
【解决方案2】:

您可以使用数值变量进行测试

 SELECT v2.id FROM vtable1 v2
WHERE
v2.group_id = 1 AND
// 6 more basic comparisons
ORDER BY score DESC LIMIT 1

无论如何,我认为使用 Join 更好,但我没有架构数据库。
也许您的 sql DB 上的索引有问题。

【讨论】:

    【解决方案3】:

    您可以使用排除连接来查找 vtable1 中的行,这样就无法找到 vtable1 中得分更高的其他行。

    UPDATE vtable2 AS v1
    INNER JOIN vtable1 AS v2a ON v1.group_id = v2a.group_id AND (...conditions...)
    LEFT OUTER JOIN vtable1 AS v2b ON v1.group_id = v2b.group_id
      AND v2a.score < v2b.score AND (...conditions...)
    SET v1.buddy = v2.id
    WHERE v2b.group_id IS NULL;
    

    对于外连接,您必须复制表达式中的所有其他条件;您不能将它们放入 WHERE 子句中。

    【讨论】:

      猜你喜欢
      • 2012-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多