2016-01-04 3 views
1

Я хочу получить две строки из моей таблицы в базе данных MySQL. эти две строки должны быть первой и последней после того, как я их приказал. Для достижения этой цели я сделал два querys, эти два:MySQL Выберите эффективную первую и последнюю строку

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

Я решил не получить весь набор и выбрать первые и последние в PHP, чтобы избежать, возможно, очень больших массивов. Моя проблема в том, что у меня есть два запроса, и я действительно не знаю, насколько это эффективно. Я хотел объединить их, например, с UNION, но тогда мне все равно пришлось бы заказать несортированный список дважды, который я также хочу избежать, потому что вторая сортировка делает то же самое, что и первая

Я хотел был бы заказать заказ а затем выберите первое и последнее значение этого упорядоченного списка, но я не знаю более эффективного способа, чем тот, у которого два запроса. Я знаю, что преимущество в производительности не будет огромным, но тем не менее я знаю, что списки растут, и по мере того как они становятся все больше и больше, и я выполняю эту часть для некоторых таблиц, мне нужен наиболее эффективный способ сделать это. Я нашел пару подобных тем, но никто из них не затронул этот конкретный вопрос.

Любая помощь очень ценится.

+5

Почему не что-то вроде 'select datebegin, max (datetimebegin), min (datetimebegin) ...'? –

+0

Я читал что-то вроде этого, но не мог понять, как именно работа. Почему я не сделал этого, я не уверен, что они сортируются дважды или нет? – JRsz

+1

не было бы сортировки вообще. вы получите наибольшее/наименьшее значение datetimebegins, а также первое задание datebegin. –

ответ

1

(Это одновременно «ответ» и опровержение ошибок в некоторых комментариях.)

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. (Кроме того, я согласен с «ответом» Гордона.)

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

не будет предоставлять много, если таковые имеются, преимущества по сравнению с двумя отдельными выбирает. Выберите технику, которая поддерживает ваш код проще.

Вы почти всегда лучше иметь одно поле DATETIME (или TIMESTAMP), чем расщепление вне DATE и/или TIME. SELECT DATE(dateTimeBegin), dateTimeBegin ... работает просто и «достаточно быстро».См. Также функцию DATE_FORMAT(). Я рекомендую отказаться от колонки dateBegin и соответствующим образом скорректировать код. Обратите внимание, что сокращение таблицы может фактически ускорить обработку больше, чем стоимость DATE(). (The дифф будет бесконечно малой.)

Без индекса начиная с dateTimeBegin, любой из методов будет медленным, и получить медленнее, таблица увеличивается в размерах. (Я уверен, что он может найти MIN() и MAX() всего за один полный проход и сделать это без сортировки. Пара ORDER BYs займет два полных прохода плюс два вида: 5.6 может иметь оптимизацию, которая почти устраняет виды.)

Если есть два ряда с точно таким же минимумом dateTimeBegin, то тот, который вы получите, будет непредсказуемым.

+0

Благодарим вас за ответ. Последнее, что вы упомянули, прекрасно, потому что меня интересует только самое низкое значение, и поэтому они могут появляться так часто, как они хотят. Поскольку значение dateTimeBegin - единственное интересное значение для меня (я больше не использую другого, поэтому это вызвало некоторую путаницу и будет удалено из моего вопроса), этот запрос работает для меня: 'SELECT MIN (dateTimeBegin) AS min, MAX (dateTimeBegin) AS max FROM worktime; ' – JRsz

2

Ваши вопросы в порядке. То, что вы хотите, - это индекс на worktime(dateTimeBegin). MySQL должен быть достаточно умным, чтобы использовать этот индекс для типов ASC и DESC. Если вы проверите это, и это не так, тогда вам понадобятся два индекса: worktime(dateTimeBegin asc) и worktime(dateTimeBegin desc).

Выполняете ли вы один запрос или два до вас. Один запрос (связанный с UNION ALL) немного более эффективен, потому что у вас есть только одна обратная связь с базой данных. Тем не менее, два могут легче вписаться в ваш код, а разница в производительности не важна для большинства целей.

Смежные вопросы