【问题标题】:optimizing query having max function优化具有最大功能的查询
【发布时间】:2011-06-24 20:13:56
【问题描述】:

我想从表格中选择一行,其中包含某些条件和某些参数 x(这是字符串)的最大值。我目前正在做:

SELECT FROM myTable mm
WHERE       mm.userId = :userId
  AND       x = (
              SELECT MAX(x)
              FROM   myTable m
              WHERE  m.userId = :userId
                AND  (m.to = :contactNumber OR m.from = :contactNumber)
                AND       ...
            )

我不确定 inno db 将如何以最佳方式执行此查询,但需要帮助改进此查询。我正在使用休眠。

【问题讨论】:

  • 所以 X 是硬连线字符串而不是来自 mm 的列?这对我来说没有意义。如果您加入了表格,您可以使用 having 子句(如果支持)来比较您的最大值
  • x 也是 myTable 的一列(mm 和 m 只是别名)

标签: sql performance hibernate optimization


【解决方案1】:
    SELECT TOP 1 * FROM myTable m
      WHERE m.userId = :userId
      AND  (m.to = :contactNumber OR m.from = :contactNumber)
      AND       ...
      ORDER BY m.x DESC

【讨论】:

  • 查看我对 Eric Petroelje 帖子的评论,不确定这是否会在大型数据集上提供良好的性能,因为会涉及到文件排序
【解决方案2】:

类似于 C.Zonnenberg 的回答,但对于 MySQL:

SELECT * FROM myTable
WHERE userId = :userId
AND  (m.to = :contactNumber OR m.from = :contactNumber)
...
ORDER BY x DESC
LIMIT 1

【讨论】:

  • An explain on this statement 说 using filesort 而且它的运行速度也比我上面的查询慢(尽管差异是小数,因为我没有现在有很多数据)。另请注意,我已按此顺序索引 (userId, to, from)
  • @kcr - 你按什么排序,你在那个字段上有索引吗?
  • 我只需要具有特定 'userId' 的行并包含条件行中 x 的最大值 (userId = 'userId' AND (m.to = :contactNumber OR m.from = : contactNumber) 以及这里的更多条件(其中不涉及 x))。我已经为 (userId, from) 编制了索引,但我想在这种情况下只能使用 userId 索引
  • @kcr - 它可能能够使用 userId 和 from 的索引,但 ORDER BY 将需要排序。因此,如果x 上没有索引,则需要进行文件排序。
  • 我的意思是我们只需要 x 最大值的行和一些其他约束,可以在 O(n) 中找到而无需排序,那么为什么要使用 O(nlgn) 文件排序
【解决方案3】:
SELECT mm.*
FROM myTable mm
  LEFT JOIN myTable m
    ON mm.UserId = m.UserId
   AND (m.to = :contactNumber OR m.from = :contactNumber)
   AND mm.x < m.x
WHERE mm.userId = :userId
  AND (mm.to = :contactNumber OR mm.from = :contactNumber)
  AND m.userId IS NULL

这使用一种已知的技术来查找最大值或最小值,使用 LEFT JOIN 到 self。基本上技术是这样的:

 SELECT a.*
 FROM a
   LEFT JOIN a AS a2 ON a.key = a2.key AND a.value < a2.value
 WHERE a2.key IS NULL

这将返回来自a 的所有行,每个key 的最大值为value。对于最低限度,您基本上将&lt; 替换为&gt;

【讨论】:

    猜你喜欢
    • 2014-01-11
    • 2015-10-24
    • 2017-12-16
    • 1970-01-01
    • 1970-01-01
    • 2014-08-06
    • 1970-01-01
    • 1970-01-01
    • 2017-06-19
    相关资源
    最近更新 更多