MySQL Select 高效的第一行和最后一行

MySQL Select efficient first and last row

我想从 MySQL 数据库中的 table 中获取两行。这两排一定是我点的第一排和最后一排。为此,我提出了两个查询,这两个:

SELECT dateBegin, dateTimeBegin FROM worktime ORDER BY dateTimeBegin ASC LIMIT 1;";
SELECT dateBegin, dateTimeBegin FROM worktime ORDER BY dateTimeBegin DESC LIMIT 1;";

我决定不获取整个集合,而是选择 PHP 中的第一个和最后一个,以避免可能出现非常大的数组。我的问题是,我有两个查询,但我真的不知道这有多有效。例如,我想将它们与 UNION 组合,但是我仍然必须两次排序未排序的列表,我也想避免,因为第二次排序与第一次排序完全相同

我想订购一次,然后 select 这个有序列表的第一个和最后一个值,但我不知道比有两个查询的方法更有效的方法。我知道性能优势不会很大,但我知道列表正在增长,并且随着它们变得越来越大,我执行这部分 tables 我需要最有效的方法来做到这一点。 我找到了几个类似的主题,但其中 none 解决了这个特定的性能问题。

非常感谢任何帮助。

你的查询没问题。您想要的是 worktime(dateTimeBegin) 上的索引。 MySQL 应该足够聪明,可以将此索引用于 ASCDESC 排序。如果您对其进行测试,但事实并非如此,那么您将需要两个索引:worktime(dateTimeBegin asc)worktime(dateTimeBegin desc).

是否 运行 一个或两个查询由您决定。一次查询(通过 UNION ALL 连接)效率稍微高一些,因为您只有一个 round-trip 到数据库。但是,两者可能更适合您的代码,并且性能差异对于大多数用途而言并不重要。

(这既是"answer"也是对部分评论错误的反驳。)

INDEX(dateTimeBegin)

将促进 SELECT ... ORDER BY dateTimeBegin ASC LIMIT 1 和另一端的相应行,使用 DESC.

MAX(dateTimeBegin) 将找到 该列的最大值;它不会直接找到该行中的其余列。这将需要一个子查询或 JOIN.

INDEX(... DESC) -- DESC 被 MySQL 忽略。这几乎从来都不是缺点,因为优化器愿意通过索引向任一方向移动。重要的是 ORDER BY x ASC, y DESC 不能 使用 INDEX(x, y),也不能 INDEX(x ASC, y DESC)。这是 MySQL 的不足。 (除此之外,我同意 Gordon 的 'answer'。)

( SELECT ... ASC )
UNION ALL
( SELECT ... DESC )

与两个单独的选择相比,如果有的话,不会提供太多的性能优势。选择使您的代码更简单的技术。

拥有一个 DATETIME(或 TIMESTAMP)字段几乎总是比拆分 DATE and/or TIME 更好。 SELECT DATE(dateTimeBegin), dateTimeBegin ... 工作简单,"fast enough"。另见函数 DATE_FORMAT()。我建议删除 dateBegin 列并相应地调整代码。请注意,缩小 table 实际上可能比 DATE() 的成本更快地加快处理速度。 (差异将是无穷小的。)

如果没有索引 starting with dateTimeBegin,任何技术都会很慢,并且随着 table 大小的增长而变慢。 (我很确定它可以在一次完整的传递中找到 both MIN()MAX(),并且无需排序。一对 ORDER BYs 需要两次完整的传递,再加上两次排序;5.6 可能有一个几乎消除排序的优化。)

如果有两行的最小值 dateTimeBegin 完全相同,你得到的那一行将是不可预测的table。