【问题标题】:MIN/MAX vs ORDER BY and LIMITMIN/MAX 与 ORDER BY 和 LIMIT
【发布时间】:2010-09-30 09:58:56
【问题描述】:

在以下查询中,您认为哪种方法更好?你的原因是什么(代码效率,更好的可维护性,更少的 WTFery)...

SELECT MIN(`field`)
FROM `tbl`;

SELECT `field`
FROM `tbl`
ORDER BY `field`
LIMIT 1;

【问题讨论】:

    标签: sql mysql


    【解决方案1】:

    在最坏的情况下,您正在查看未索引的字段,使用MIN() 需要对表进行一次完整传递。使用 SORTLIMIT 需要文件排序。如果针对大型表运行,则感知性能可能会有显着差异。作为一个轶事数据点,MIN() 花费了 0.36 秒,而 SORTLIMIT 在我的开发服务器上的 106,000 行表中花费了 0.84 秒。

    但是,如果您正在查看索引列,则很难注意到差异(在这两种情况下,无意义的数据点都是 0.00 秒)。然而,看看 explain 的输出,看起来 MIN() 能够简单地从索引中提取最小值(“选择优化掉的表”和“NULL”行),而 SORTLIMIT 仍然需要需要对索引(106,000 行)进行有序遍历。实际的性能影响可能可以忽略不计。

    看起来MIN() 是要走的路——它在最坏的情况下更快,在最好的情况下难以区分,是标准 SQL,最清楚地表达了您想要获得的价值。似乎需要使用SORTLIMIT 的唯一情况是,正如mson 提到的那样,您正在编写一个从任意列中查找顶部或底部N 值的通用操作,这是不值得的写出特殊情况的操作。

    【讨论】:

    • o(n) 单次通过 vs 0(nlogn) 排序
    • @AbhishekIyer 你是完全正确的,但我会添加“在最坏的情况下未索引字段”。
    • 关于最坏的未索引情况的部分是错误的。您总是需要全面扫描,否则您怎么知道它是最小还是最大?这不像是你在扫描,价值尖叫:“嘿,你终于找到我了!我是杰克,max!”。
    • 在一个包含 4.7 亿行的索引表的测试中,两个查询都需要 0.00 秒。但是,如果我们在查询中添加过滤器“WHERE field2=x”,则带有 LIMIT 的查询仍然需要 0.00 秒,而带有 MIN 的查询需要 0.21 秒。
    • 这取决于您的表和数据库设置。我们刚刚通过从带有limitorder by 到带有maxgroup by 将具有>10M 行的数据库从多秒减少到亚秒。逻辑应该很容易理解。除了迭代,您需要检索 n 行或 1 行。
    【解决方案2】:
    SELECT MIN(`field`)
    FROM `tbl`;
    

    仅仅是因为它与 ANSI 兼容。限制 1 是特定于 MySql 的,因为 TOP 是特定于 SQL Server。

    【讨论】:

    • 大多数 DBMS 都有限制/偏移或等效项,它用于我开发的大多数应用程序中(不是 MIN 的替代品,而是用于分页等其他目的。)
    • @finnw - 我同意,但提问者的例子是明确比较 limit 和 min。
    【解决方案3】:

    正如msonSean McSomething 所指出的,MIN 更可取。

    ORDER BY + LIMIT 有用的另一个原因是,如果您想要获取与 MIN 列不同的列的值。

    例子:

    SELECT some_other_field, field
    FROM tbl
    ORDER BY field
    LIMIT 1
    

    【讨论】:

    • 在这种情况下是否更可取?或使用最大/最小的嵌套查询? (SELECT some_other_field, field FROM tbl WHERE field = ( SELECT MIN(field) FROM tbl ))
    【解决方案4】:

    我认为答案取决于你在做什么。

    如果您有一个 1 off 查询并且意图与您指定的一样简单,则最好选择 min(field)。

    但是,这些类型的需求通常会更改为 - 获取前 n 个结果、获取第 n 个 - 第 m 个结果等。

    我不认为提交到您选择的数据库是一个太糟糕的想法。更改数据库不应该掉以轻心,必须修改的是您做出此举动时所付出的代价。

    为什么现在限制自己,因为您以后可能会或可能不会感到痛苦?

    我确实认为尽可能保持 ANSI 是好的,但这只是一个指导方针......

    【讨论】:

      【解决方案5】:

      考虑到可接受的性能,我会使用第一个,因为它在语义上更接近意图。
      如果性能是一个问题,(大多数现代优化器可能会将两者优化到相同的查询计划,尽管您必须测试以验证这一点)那么我当然会使用更快的。

      【讨论】:

        【解决方案6】:

        user650654 表示,当需要“获取与 MIN 列不同的列的值”时,使用 LIMIT 1 的 ORDER BY 很有用。我认为,在这种情况下,使用 MIN 而不是排序,我们仍然可以通过两次单次传递获得更好的性能(希望这是优化的 :()

        SELECT some_other_field, field
        FROM tbl
        WHERE field=(SELECT MIN(field) FROM tbl)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-03-18
          • 2014-01-09
          • 1970-01-01
          • 2023-03-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多