Яким чином MySQL обробляє ЗАМОВЛЕННЯ ЗА ВИМОГАМИ та ОБМЕЖЕННЯ у запиті?


250

У мене є запит, який виглядає приблизно так:

SELECT article FROM table1 ORDER BY publish_date LIMIT 20

Як працює ЗАМОВЛЕННЯ? Чи він замовить усі записи, потім отримає перші 20, або отримає 20 записів і замовить їх по publish_dateполю?

Якщо це остання, ви не гарантовано отримаєте останні 20 статей.


6
Зауважте, що якщо деякі publish_dates рівні, упорядкування ними не дає визначених результатів, це означає, що якщо ви використовуєте LIMITдля пагинації, ви можете отримати однакові елементи на різних сторінках!
Конрад Моравський

Відповіді:


244

Він спочатку замовить, а потім отримає перший 20. База даних також обробляє все, що було WHEREраніше в пункті ORDER BY.


1
Тож терміни однакові?
Ясар Арафат

7
Неправильно! LIMITперерви ORDER BY. З LIMITв ORDER BYрезультаті повертає неправильний. LIMITякимось чином переставляє набір результатів, поверненийORDER BY
Зелений

6
@Green, ти помилився. Прочитайте це для пояснення: dev.mysql.com/doc/refman/5.7/en/limit-optimization.html Коли стовпець ORDER BY індексується, він може повертати записи в іншому порядку, ніж без ОБМЕЖЕННЯ, коли є більше ніж 1 запис із однаковим значенням у цьому стовпці.
yitwail

1
Одне швидке рішення таких проблем - додати ще один стовпець на замовлення, бажано мати унікальні значення, щоб база даних отримувала послідовне правило для впорядкування рядків, коли значення першого порядку за стовпцем однакове для кількох рядків.
rineez

37

Застереження LIMIT може використовуватися для обмеження кількості рядків, повернених оператором SELECT. LIMIT приймає один або два числові аргументи, які повинні бути невід’ємними цілими константами (за винятком випадків використання підготовлених операторів).

З двома аргументами перший аргумент вказує зміщення першого рядка для повернення, а другий визначає максимальну кількість рядків для повернення. Зсув початкового рядка дорівнює 0 (не 1):

SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15

Щоб отримати всі рядки від певного зміщення до кінця набору результатів, ви можете використовувати деяке велике число для другого параметра. Це твердження отримує всі рядки з 96-го ряду до останнього:

SELECT * FROM tbl LIMIT 95,18446744073709551615;

За допомогою одного аргументу значення визначає кількість рядків, які потрібно повернути з початку набору результатів:

SELECT * FROM tbl LIMIT 5; # Retrieve first 5 rows

Іншими словами, LIMIT row_count еквівалентно LIMIT 0, row_count.

Всі деталі на сайті: http://dev.mysql.com/doc/refman/5.0/uk/select.html


Чи не витягуйте рядки 5-14?
Адоніс К. Какулідіс

@adonis Ні, це не так. Приклад прямо з документації MySQL
dcaswell

Число 5 - 6-й ряд. 5 рядків (від 0 до 4) ігноруються.
Філ Перрі

1
Але використання LIMIT без ЗАМОВЛЕННЯ BY може дати непослідовні результати! На жаль, весь набір результатів повинен бути впорядкований до того, як буде застосовано LIMIT або СУБД може вільно довільно замовляти результат, а потім OFFSET та LIMIT на цьому наборі. Я читав, що це може бути пов'язано з вибором СУБД альтернативного плану запитів на основі OFFSET та LIMIT, таким чином, довільного порядку.
Бартон

4
питання задає ліміт і замовити. Але відповідь взагалі не пов’язана з цим питанням
Shen laang

9

Як говорить @James, він упорядкує всі записи, а потім отримає перші 20 рядків.

Оскільки це так, ви гарантовано отримаєте 20 перших опублікованих статей, новіші не відображатимуться.

У вашій ситуації я рекомендую додати descдо order by publish_date, якщо ви хочете , то найновіші статті, то новітня стаття буде першою.

Якщо вам потрібно зберегти результат у порядку зростання, і все ще хочете лише 10 найновіших статей, ви можете попросити mysql сортувати результат у два рази.

Цей запит нижче буде сортувати результат за спаданням і обмежує результат до 10 (тобто запит всередині дужок). Він все ще буде відсортований у порядку зменшення, і нас це не влаштовує, тому ми просимо mysql сортувати його ще раз. Тепер у нас є останній результат в останньому ряду.

select t.article 
from 
    (select article, publish_date 
     from table1
     order by publish_date desc limit 10) t 

order by t.publish_date asc;

Якщо вам потрібні всі стовпці, це робиться так:

select t.* 
from 
    (select * 
     from table1  
     order by publish_date desc limit 10) t 

order by t.publish_date asc;

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


2
Ваша додаткова сортування практично не може мати жодного вимірюваного впливу на продуктивність, оскільки вона обмежена лише 10 рядками / елементами :-). Взагалі сортування таблиці в пам'яті (яку виробляє підбір) дуже швидко і ледве виміряється, якщо у вас мільйони рядків або СУБД не підписує набір результатів на диск, оскільки він не відповідає пам'яті (в такому випадку залежно від СУБД, вона також може скасувати запит).
Мартін Керстен

7

Якщо в полі є відповідний індекс, то в цьому випадку на publish_dateMySQL не потрібно сканувати весь індекс, щоб отримати 20 запитуваних записів - 20 записів знайдуться на початку індексу. Але якщо немає відповідного індексу, знадобиться повне сканування таблиці.

Про це є стаття в блозі продуктивності MySQL від 2009 року.


7

Ви можете додати [asc] або [desc] наприкінці замовлення, щоб отримати найдавніші чи останні записи

Наприклад, спочатку ви отримаєте останні записи

ORDER BY stamp DESC

Додайте LIMITпункт післяORDER BY


3
Ласкаво просимо в stackoverflow. Я думаю, ви, можливо, неправильно зрозуміли питання. Я вважаю, що вони питали про порядок операцій, а не про те, як "сортувати". (Але це суперечка, оскільки на запитання вже відповіли деякий час тому;)
Лі,

5

Ви можете використовувати цей код, SELECT article FROM table1 ORDER BY publish_date LIMIT 0,10 коли 0 - це початкова межа запису та 10 - кількість записів


8
Ні, це не потрібно . LIMIT 10це скорочення для LIMIT 0,10.
Лоуренс Дол

2
так, не потрібно для ОБМЕЖЕННЯ 0,10 Але Ви можете вимагати, як цей ліміт 10,20
gaurangkathiriya

3

LIMIT зазвичай застосовується як остання операція, тому результат спочатку буде відсортований, а потім обмежений 20. Насправді сортування припиняється, як тільки будуть знайдені перші 20 відсортованих результатів.


11
Ваше друге речення йде проти вашого першого. Сортування не може зупинитися, коли знайдеться перші 20 результатів, оскільки, як ви вже сказали, сортування буде здійснено до повернення результатів. MySQL може знати лише перші 20 результатів після сортування.
Том

@Tom, насправді це може, якщо замовити індексовану колонку. Це пояснено тут: dev.mysql.com/doc/refman/5.7/uk/limit-optimization.html
yitwail

-3

Також синтаксис LIMIT відрізняється залежно від баз даних, наприклад:

mysql - ОБМЕЖЕННЯ 1, 2

postgres - ОБМЕЖЕННЯ 2 ВИМОГИ

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.