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 应该足够聪明,可以将此索引用于 ASC
和 DESC
排序。如果您对其进行测试,但事实并非如此,那么您将需要两个索引: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。
我想从 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 应该足够聪明,可以将此索引用于 ASC
和 DESC
排序。如果您对其进行测试,但事实并非如此,那么您将需要两个索引: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。