Оптимизация ORDER BY — о чем многие забывают / Хабр
На тему оптимизации MySQL запросов написано очень много, все знают как оптимизировать SELECT, INSERT, что нужно джоинить по ключу и т.д. и т.п.Но есть один момент, тоже неоднократно описанный во всех мануалах, но почему-то про него все забывают.
Оптимизация ORDER BY в запросах с джоинами.
Оправдание: поиском воспользовался, не нашел !Большинство считают, что если ORDER BY происходит по индексу, то и проблем никаких нет, однако это не всегда так. Недавно я разбирался с одним запросом который дико тормозил базу хотя вроде все индексы на нужных местах. ORDER BY оказался последним местом, куда я ткнулся, и проблема оказалась именно там.
Маленькая выдержка из мануалов по оптимизации:
===
Как MySQL оптимизирует ORDER BY
Ниже приведены некоторые случаи, когда MySQLне может использовать индексы, чтобы выполнить ORDER BY
…
Связываются несколько таблиц, и столбцы, по которым делается
сортировка ORDER BY, относятся не только к первой неконстантной
(const) таблице, используемой для выборки строк(это первая таблица
в выводе EXPLAIN, в которой не используется константный, const, метод выборки строк).
…
===
Для ORDER BY важно, чтобы таблица, по которой будет производиться сортировка была на первом месте. Однако по умолчанаю, в каком бы порядке вы не джойнили таблицы, встроенный в mysql оптимизатор переставит их в том порядке, как он сам посчитает нужным. То есть если вы поставили нужную таблицу первой в запросе, то это вовсе не означает, что она будет на самом деле первой.
К счастью, оптимизатору mysql можно сказать, чтобы он джоинил таблицы в том порядке, какой мы ему указали, для этого нужно в SELECT добавить команду STRAIGHT_JOIN:
SELECT STRAIGHT_JOIN… FROM table JOIN…… ORDER BY table.row
Проверка на mysql базе форума PHPBB3 содержащей около 300 000 постов:
SELECT t.*, p.*, u.username FROM phpbb3_topics as t, phpbb3_posts as p, phpbb3_users as u WHERE t.topic_replies>0 AND p.poster_id=u.user_id AND topic_first_post_id<>p.post_id AND topic_approved=1 AND p.topic_id=t.topic_id AND t.forum_id='16' AND p.post_id<'244103' ORDER by post_id desc LIMIT 40
Query took 12. 2571 sec
в explain видим ужасное: Using where; Using temporary; Using filesort
Меняем порядок таблиц (кеш мускуля сбросил перезагрузкой):
SELECT STRAIGHT_JOIN t.*, p.*, u.username FROM phpbb3_posts as p, phpbb3_topics as t, phpbb3_users as u WHERE t.topic_replies>0 AND p.poster_id=u.user_id AND topic_first_post_id<>p.post_id AND topic_approved=1 AND p.topic_id=t.topic_id AND t.forum_id='13' AND p.post_id<'234103' ORDER by post_id desc LIMIT 40
Query took 0.0447 sec
в explain: Using where;
Вот такой принудительной перестановкой таблиц мы ускорили выполнение запроса в 300 раз!
Это совсем не значит, что нужно всегда использовать STRAIGHT_JOIN и самому следить за порядком таблиц. Но в некоторых случах это необходимо.
P.S. Этот запрос используется Яндексом для индексации форумов phpbb. До оптимизации, яндекс-бот клал сервер php.ru каждую ночь на несколько часов (сервер не очень мощный). В блоге Яндекса была дисскуссия на эту тему, но она закрыта пару лет назад и решение там не озвучено.
MySQL ORDER BY DESC | Как работает ORDER BY DESC в MySQL?
Обновлено 31 мая 2023 г.
MySQL ORDER BY DESC — это предложение ORDER BY в MySQL, которое отвечает за сортировку записей базы данных при их выборке в виде строк результата.
По сути, предложение ORDER BY использует атрибуты для указания порядка сортировки записей таблицы. Поэтому нам нужно включить модификаторы ASC или DESC с предложением ORDER BY для этой команды запроса.
Атрибуты в сочетании с предложением ORDER BY определяют расположение строк в таблице результатов в порядке возрастания или убывания. Однако по умолчанию предложение ORDER BY в MySQL автоматически устанавливает значение ASC (по возрастанию), если модификатор не указан. Итак, мы реализуем запрос ORDER BY DESC для получения строк в порядке убывания.
Синтаксис
Последующий синтаксис представляет собой простую структуру для применения предложения ORDER BY DESC к запросу базы данных MySQL:
SELECT ColumnName1, ColumnName2, …. FROM TableName WHERE Cond_Expr ORDER BY ColumnName1 DESC, ColumnName2DESC,….ColumnNameNDESC;
Давайте объясним синтаксис ниже:
- Чтобы применить предложение ORDER BY DESC, мы будем использовать оператор SELECT для написания запроса.
- ColumnName обозначает имена столбцов таблицы, которые пользователь хочет получить.
- TableName обозначает имя таблицы, включенной в запрос.
- Предложение WHERE определяет условное выражение, которое таблица применяет для предоставления результата. Это необязательное условие используется для определения строк, отображаемых в результирующем наборе, когда оно удовлетворяется.
- Предложение ORDER BY с DESC определяет структуру упорядочения с определенным именем столбца.
Как работает ORDER BY DESC в MySQL?
- Реализация оператора SELECT в запросе MySQL будет извлекать записи данных из определенной таблицы; затем вы заметите, что предоставленная таблица строк результатов не имеет упорядоченной формы.
- С помощью предложения ORDER BY вы можете упорядочить строки с любым конкретным именем столбца. Чтобы в дальнейшем результат отображался в отсортированном виде, то есть в порядке возрастания или убывания, мы будем использовать ключевые слова ASC или DESC, которые определяют атрибуты для этого предложения ORDER BY.
- Предложение ORDER BY использует ключевое слово DESC для получения записей в порядке убывания. Мы можем указать один или несколько столбцов таблицы для сортировки после предложения ORDER BY, разделив список столбцов запятыми. Важно отметить, что разные столбцы можно сортировать по-разному, используя ключевые слова ASC или DESC после ORDER BY, следуя указанному синтаксису. Как показано ниже:
ВЫБЕРИТЕ ИмяСтолбца1, ИмяСтолбца2, …. FROM TableName ORDER BY ColumnName1 ASC, ColumnName2 DESC,….ColumnNameN [ASC | ПОИСК];
Таким образом, строки результатов будут отсортированы определенным образом.
Примеры MySQL ORDER BY DESC
Давайте продемонстрируем несколько примеров с предложением ORDER BY DESC и увидим его использование и работу с ним в MySQL:
Пример №1 — MySQL ORDER BY DESC с использованием одного столбца таблицы для иллюстрации; мы возьмем образец таблицы в нашей базе данных с именем «Клиент», имеющей поля CusotmerID, CutomerName, Credit_Limit и City. Просмотрите содержимое таблицы следующим образом:
ВЫБЕРИТЕ * ОТ Заказчика;
Вывод:
Давайте запросим записи данных из таблицы Customer, чтобы отобразить результат, используя предложение ORDER BY просто без атрибута:
SELECT CustomerID, CustomerName, City FROM Customer ORDER BY CustomerName;
Выходные данные:
Из приведенного выше вывода видно, что строки результатов по умолчанию сортируются в порядке возрастания, даже если ключевые слова ASC и DESC не указаны явно.
Теперь давайте напишем запрос с использованием предложения MySQL ORDER BY DESC для сортировки набора результатов запроса по определенному столбцу таблицы в порядке убывания:
SELECT CustomerID, CustomerName, City FROM Customer ORDER BY CustomerName DESC;
Вывод:
Чтобы увидеть разницу, вы можете использовать модификатор DESC с предложением ORDER BY, который сортирует содержимое в порядке убывания. Например, столбец CustomerName в запросе указан с ORDER BY DESC.
Пример #2 — MySQL ORDER BY DESC с использованием нескольких столбцов таблицы
Мы будем использовать предложение MySQL ORDER BY DESC с несколькими столбцами таблицы в запросе и увидим набор результатов при выполнении. Оператор MySQL, запрашивающий ту же таблицу Customer, что и предыдущий, выглядит следующим образом:
SELECT CustomerID, CustomerName, City FROM Customer ORDER BY CustomerName DESC, City DESC;
Вывод:
Здесь мы использовали ключевые слова DESC с обоими именами столбцов после предложения ORDER BY, чтобы получить результирующий набор в порядке убывания. Таким образом, если один столбец указан с модификатором DESC, а другой столбец — нет, результат будет автоматически отсортирован в порядке возрастания.
Пример №3. MySQL ORDER BY DESC с использованием предложения WHERE
Предположим, нам нужно сгенерировать результирующий набор с клиентами, имеющими кредитный лимит больше или равный 3000, из того же запроса, что и использование предложения ORDER BY DESC для выборки строк результатов. . Мы запросим записи с предложением WHERE следующим образом:
SELECT CustomerName, City, Credit_LimitFROM Customer WHERE Credit_Limit>=3000 ORDER BY City DESC;
Вывод:
Пример №4 — MySQL ORDER BY DESC с использованием опции LIMIT
Мы можем применить предложение LIMIT, которое позволяет ограничить количество строк, извлекаемых в результирующем наборе. Мы будем использовать вместе с предложением ORDER BY DESC опцию LIMIT в конце, чтобы увидеть результаты. Возьмем предыдущий пример и немного изменим его, как показано ниже:
SELECT * FROM Customer WHERE Credit_Limit>=1500 ORDER BY Credit_Limit DESC;
Вывод:
Здесь мы просто получили результаты, имеющие 6 строк с порядком по кредитному лимиту столбца и предложением WHERE. Теперь, используя LIMIT, запрос становится следующим:
SELECT * FROM Customer WHERE Credit_Limit>=1500 ORDER BY Credit_LimitDESC LIMIT 3;
Вывод:
Теперь посмотрите на вывод; строки результатов сокращаются до 3, как уже упоминалось, а кредитный лимит находится в порядке убывания, как указано в запросе выше.
Заключение
Предложение ORDER BY, сопровождаемое атрибутом-модификатором DESC, определяет порядок сортировки строк таблицы при выборке с помощью запроса. Если какой-либо атрибут не указан в запросе для предложения ORDER BY, то по умолчанию строки результатов будут упорядочены по возрастанию.
В MySQL вы можете применять предложение ORDER BY DESC в операторах SELECT LIMIT, SELECT и DELETE LIMIT.
Рекомендованные статьи
Мы надеемся, что эта информация EDUCBA о «ORDER BY DESC MySQL» была вам полезна. Вы можете просмотреть рекомендуемые статьи EDUCBA для получения дополнительной информации.
- MySQL ЗАМЕНИТЬ
- Работа MySQL UNIQUE INDEX
- MySQL SYSDATE()
- PostgreSQL DATE_PART()
Как использовать ORDER BY и CAST в MySQL
Во многих случаях, когда вы работаете с запросами SQL, очень важно иметь отформатированные данные, когда они возвращаются. Один из способов форматирования — вы можете видеть вещи в определенном порядке. Например, прямо сейчас, если я просто скажу SELECT guides_title FROM guides
, и если я запущу этот запрос, он вернет все результаты.
Результаты будут просто отсортированы по идентификатору, который используется по умолчанию для запуска SQL. Итак, если я запущу этот код, вы увидите, что в нем есть «мой блог», «что-то еще», «мой замечательный пост», «мой блог» и «мой блог», и это может быть нормально. Однако у нас также есть возможность добавить предложение ORDER BY, которое позволит нам сортировать данные по мере их поступления и набор результатов.
Итак, чтобы сделать это, мы добавим еще одну строку и скажем «ORDER BY», а затем вы выберете параметр, по которому хотите упорядочить. Итак, здесь я скажу guides_title, а затем вы скажете, хотите ли вы, чтобы он был нисходящим или восходящим. Сначала будем делать спуск.
Теперь, если я запущу этот код, вы увидите, что теперь он отсортирован и содержит «что-то еще», «Мой замечательный пост» и «мой блог». Это все точно отсортировано. Если бы я скопировал это и отсортировал по возрастанию, это был бы тот же набор результатов. Это просто будет перевернуто. Поэтому, если я запущу его снова сейчас, вы увидите, что он отсортирован по алфавиту.
Теперь я хочу показать вам кое-что, что может показаться немного странным. Если я вставлю это и скажу, что мне нужен guides_title, но еще до этого я хочу получить guides_revenue. Тогда я на самом деле хочу отсортировать по доходу, и я попытаюсь сделать это по убыванию. Теперь, если я запущу этот запрос, он будет работать, поскольку он не выдает ошибку.
Однако я хочу, чтобы вы заметили здесь кое-что немного странное. Итак, по умолчанию MySQL работает следующим образом: он обрабатывает это и говорит 750, 750, 500, 1300, а затем 1000. Ну, в этом нет никакого смысла. Если мы сортируем по убыванию, мы ожидаем, что сможем увидеть самые большие числа вплоть до самых маленьких. Теперь, если я переключу это на возрастание и обработаю это, вы увидите, что оно ведет себя более странно.
Это определенно не то, что вы ожидаете. Когда я впервые изучал SQL, эта часть была для меня довольно запутанной.
Проблема в том, что когда мы пытаемся упорядочить что-то вроде буквенно-цифрового, например, guides_title, это работает отлично. Однако guides_revenue Если вы помните, если вы посмотрите на схему, то способ, которым мы ее структурировали, был немного другим. Итак, если мы пойдем к нашим столам за руководствами, и если я посмотрю на инспектора схемы в столбцах.
Вы можете видеть, что у нас есть это целое число с 11 VARchar прямо здесь. Таким образом, это не совсем с точки зрения доходов. На самом деле это не имеет никакого смысла, потому что он пытается просто взять все элементы и обрабатывает их как буквенно-цифровые значения, хотя на самом деле это числа.
Это классная вещь, и это одна из причин, по которой мы настроили этот тип данных. Я хочу, чтобы вы видели, что это будет происходить много раз, когда вы работаете с такими вещами, как устаревшие приложения для работы с данными. Где элемент в этом атрибуте данных столбца не соответствует вашим ожиданиям. Здесь же для guides_revenue задано значение varchar.
Вероятно, не то, что вы ожидаете от чего-то вроде дохода. Но будут времена, когда вам придется с этим смириться. Способ, которым вы можете это исправить, — это выполнение так называемого CASTing. Итак, что делает приведение, так это то, что оно дает вам возможность изменять тип данных на лету для поступающих значений.0003
Здесь я скажу приведение как беззнаковое, а затем мы сделаем по возрастанию. Что это собирается сделать, так это ввести эти значения и вместо того, чтобы обрабатывать их так же, как буквенно-цифровые символы. Он будет приводить его к беззнаковому типу данных, что означает, что он будет рассматривать его как число, и именно это представляет беззнаковый тип.
Итак, теперь давайте запустим это, и я обработаю его, теперь вы можете видеть, что теперь это работает.
Итак, когда у меня есть возрастание, наименьшее число здесь находится вверху, а затем внизу есть самое большое число.