简体   繁体   English

MySQL选择有效的第一行和最后一行

[英]MySQL Select efficient first and last row

I want to get two rows from my table in a MySQL databse. 我想在MySQL数据库中从我的表中获取两行。 these two rows must be the first one and last one after I ordered them. 在我订购它们之后,这两行必须是第一行和最后一行。 To achieve this i made two querys, these two: 为了达到这个目的,我做了两个查询,这两个:

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

I decided to not get the entire set and pick the first and last in PHP to avoid possibly very large arrays. 我决定不使用整个集合并在PHP中选择第一个和最后一个以避免可能非常大的数组。 My problem is, that I have two querys and I do not really know how efficient this is. 我的问题是,我有两个查询,我真的不知道这有多高效。 I wanted to combine them for example with UNION, but then I would still have to order an unsorted list twice which I also want to avoid, because the second sorting does exactly the same as the first 我想将它们与例如UNION组合在一起,但是我仍然需要两次排序未排序的列表,我也想避免,因为第二次排序与第一次排序完全相同

I would like to order once and then select the first and last value of this ordered list, but I do not know a more efficient way then the one with two querys. 我想订购一次,然后选择这个有序列表的第一个和最后一个值,但我不知道一个有两个查询的方法更有效。 I know the perfomance benefit will not be gigantic, but nevertheless I know that the lists are growing and as they get bigger and bigger and I execute this part for some tables I need the most efficient way to do this. 我知道性能优势不会很大,但我知道这些列表正在增长,随着它们变得越来越大,我为某些表执行此部分,我需要最有效的方法来实现这一点。 I found a couple of similar topics, but none of them adressed this particular perfomance question. 我发现了几个类似的主题,但没有一个主题解决这个特定的性能问题。

Any help is highly appreciated. 任何帮助都非常感谢。

Your queries are fine. 你的查询很好。 What you want is an index on worktime(dateTimeBegin) . 你想要的是工作时间的索引worktime(dateTimeBegin) MySQL should be smart enough to use this index for both the ASC and DESC sorts. MySQL应该足够聪明,可以将此索引用于ASCDESC排序。 If you test it out, and it is not, then you'll want two indexes: worktime(dateTimeBegin asc) and worktime(dateTimeBegin desc) . 如果你测试它,但它不是,那么你需要两个索引: worktime(dateTimeBegin asc)worktime(dateTimeBegin desc)

Whether you run one query or two is up to you. 是否运行一个或两个查询取决于您。 One query (connected by UNION ALL ) is slightly more efficient, because you have only one round-trip to the database. 一个查询(由UNION ALL连接)稍微提高效率,因为您只有一次往返数据库。 However, two might fit more easily into your code, and the difference in performance is unimportant for most purposes. 但是,两个可能更容易适合您的代码,并且性能的差异对于大多数目的而言并不重要。

(This is both an "answer" and a rebuttal to errors in some of the comments.) (这既是一个“答案”,也是对一些评论中错误的反驳。)

INDEX(dateTimeBegin)

will facilitate SELECT ... ORDER BY dateTimeBegin ASC LIMIT 1 and the corresponding row from the other end, using DESC . 将使用DESC促进SELECT ... ORDER BY dateTimeBegin ASC LIMIT 1和来自另一端的相应行。

MAX(dateTimeBegin) will find only the max value for that column; MAX(dateTimeBegin)会发现只有该列的最大值; it will not directly find the rest of the columns in that row. 不会直接找到该行中的其余列。 That would require a subquery or JOIN . 这将需要子查询或JOIN

INDEX(... DESC) -- The DESC is ignored by MySQL. INDEX(... DESC) - MySQL 忽略DESC This is almost never a drawback, since the optimizer is willing to go either direction through an index. 这几乎从来都不是一个缺点,因为优化器愿意通过索引进行任一方向。 The case where it does matter is ORDER BY x ASC, y DESC cannot use INDEX(x, y) , nor INDEX(x ASC, y DESC) . 它确实重要的情况是ORDER BY x ASC, y DESC 不能使用INDEX(x, y) ,也不能使用INDEX(x ASC, y DESC) This is a MySQL deficiency. 这是MySQL的缺陷。 (Other than that, I agree with Gordon's 'answer'.) (除此之外,我同意戈登的'回答'。)

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

won't provide much, if any, performance advantage over two separate selects. 与两个单独的选择相比,它不会提供太多(如果有的话)性能优势。 Pick the technique that keeps your code simpler. 选择让您的代码更简单的技术。

You are almost always better off having a single DATETIME (or TIMESTAMP ) field than splitting out the DATE and/or TIME . 拥有单个DATETIME (或TIMESTAMP )字段比分割DATE和/或TIME几乎总是更好。 SELECT DATE(dateTimeBegin), dateTimeBegin ... works simply, and "fast enough". SELECT DATE(dateTimeBegin), dateTimeBegin ...工作简单,“足够快”。 See also the function DATE_FORMAT() . 另请参见函数DATE_FORMAT() I recommend dropping the dateBegin column and adjusting the code accordingly. 我建议删除dateBegin列并相应地调整代码。 Note that shrinking the table may actually speed up the processing more than the cost of DATE() . 请注意,缩小表可能实际上加快处理速度而不是DATE()的成本。 (The diff will be infinitesimal.) (差异将是无穷小的。)

Without an index starting with dateTimeBegin , any of the techniques would be slow, and get slower as the table grows in size. 如果没有以dateTimeBegin 开头的索引,任何技术都会很慢,并且随着表的大小增长而变慢。 (I'm pretty sure it can find both the MIN() and MAX() in only one full pass, and do it without sorting. The pair of ORDER BYs would take two full passes, plus two sorts; 5.6 may have an optimization that almost eliminates the sorts.) (我敢肯定它可以发现无论MIN()MAX()只在一个全面检查,并做到这一点不排序的一对。 ORDER BYs将采取两个完整的传球,加上两类; 5.6可有优化这几乎消除了种类。)

If there are two rows with exactly the same min dateTimeBegin , which one you get will be unpredictable. 如果有两行具有完全相同的min dateTimeBegin ,那么您得到的哪一行将是不可预测的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM