Site icon IT-блог о Linux, DevOps и серверных технологиях
Пятница, 13 марта, 2026

Быстрая нумерация страниц в Mysql — почему order с Limit и смещением является медленным?

Быстрая нумерация страниц в Mysql - почему order с Limit и смещением является медленным?

Запросы с LIMIT и OFFSET распространены в приложениях, которые требуют нумерации страниц, а в некоторых случаях могут работать некоторое время.

Однако во многих случаях они становятся медленными и болезненными, когда значение OFFSET имеет высокое значение.

 

Почему OFFSET такой медленный?

Ну, в большинстве случаев запросы с низким смещением не медленные. Проблема начинается с высоких значений смещения.

Если ваш запрос использует следующее предельное условие: «LIMIT 50000, 20», он фактически запрашивает у базы данных 5050 строк и отбрасывает первые 50 000. Это действие может иметь высокую стоимость, время отклика на воздействие.

Вы можете спросить себя: «Кто, черт возьми, собирается пропустить страницу 50 000 в моем заявлении?».
Давайте перечислим несколько возможных вариантов использования:

Протестируем следующие значения OFFSET с помощью следующего запроса, чтобы представить снижение производительности по мере роста OFFSET.

Запрос был выполнен для таблицы, содержащей пользовательские события (таблица аналитики) с 150 000 записей. Данные являются реальной информацией пользователя и не генерируются автоматически.

SELECT
*
FROM
events
WHERE
date > '2019-04-12T00:00:00-00:00'
AND event = 'editstart'
ORDER BY date
LIMIT 50;

 

Offset Query Duration (ms)
0 1
50 1
1000 13
10000 150
25000 500
50000 930
100000 1750

 

 

Быстрее нумерация страниц в Mysql - почему order с Limit и смещением является медленным?

 

Как оптимизировать медленные OFFSET запросы?

Чтобы оптимизировать медленные запросы OFFSET, вы можете либо ограничить количество разрешенных страниц в представлении нумерации страниц, либо просто не использовать OFFSET.

Хорошей альтернативой использованию OFFSET будет метод поиска.

Проще говоря, метод поиска — это поиск уникального столбца или набора столбцов, который идентифицирует каждую строку. Затем, вместо использования предложения OFFSET, мы можем просто использовать это уникальное значение в качестве закладки, которая представляет позицию последней выбранной строки, и запросить следующий набор строк, начиная с этой позиции в предложении WHERE.

Например, если посмотреть на запросы, которые мы выполняли ранее, предполагая, что последний идентификатор события со смещением 999 999 равнялся ‘111866’, запрос будет:

SELECT    *
FROM
events
WHERE
(date,id) > ('2019-04-12T10:29:47-07:00',111866)
AND event = 'editstart'
ORDER BY date, id
LIMIT 10

 

Другой способ написать запрос:

SELECT    *
FROM
events
WHERE
date>='2019-04-12T10:29:47-07:00' and not (date='2019-04-12T10:29:47-07:00' and id < 111866)
AND event = 'editstart'
ORDER BY date, id
LIMIT 10

 

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

Это сравнение производительности обоих методов. Интересное наблюдение здесь заключается не только в том, что производительность метода Seek лучше, но и в том, что он более стабилен, независимо от того, как далеко вы разбиваетесь на таблицы.

Быстрее нумерация страниц в Mysql - почему order с Limit и смещением является медленным?

 

Возможные подводные камни/проблемы

 

 

Заключение

Мы не рекомендуем использовать функцию OFFSET в MySQL для реализации возможностей подкачки. Когда данные растут, вы, вероятно, начнете замечать проблемы с производительностью. Вместо этого рассмотрите возможность использования метода поиска, описанного выше.

Exit mobile version