#mysql #performance #pagination #cursor #offset
#mysql #Производительность #разбивка на страницы #курсор #смещение
Вопрос:
Мне нужно разбить на страницы более 30 миллионов пользователей, размещенных на MySQL. Я показываю 15 пользователей на страницу, но это довольно медленно. Моя цель — получить доступ к любой случайной странице и загрузить ее за несколько мс.
Вначале я использовал метод смещения для MySQL, но, как я уже сказал, он довольно медленный (и, конечно, плохая идея). Затем я перешел на ElasticSearch, но у вас все еще есть некоторый предел окна, поэтому вы ограничены. После этого я проверял различные способы, такие как метод «курсор», но я не могу получить доступ к какой-либо случайной странице. Например, мы начинаем с первой страницы, и у нас 100000 страниц, я хотел бы получить доступ к 4782-й странице и загрузить ее за несколько мс. С помощью метода cursor я просто могу получить доступ к следующей amp;amp; предыдущей странице, а метод «прокрутки» не соответствует тому, что мне действительно нужно.
Идентификатор моих пользователей сортируется не только по идентификатору, поэтому я не могу использовать его в качестве разделителя. Уже думал о поздних поисках строк
Я не против перенести все свои данные в новую базу данных (но нужно было бы найти другие решения). Здесь Amazon делает это действительно хорошо (https://www.amazon.com/review/top-reviewers )
Запрос с использованием смещения:
SELECT users.* from users
WHERE users.country = 'DE'
ORDER BY users.posts_count DESC, users.id DESC
LIMIT 15 OFFSET 473
PD: Мой список пользователей работает почти в режиме реального времени, поэтому он меняется каждый час.
Есть идеи? Большое спасибо!
Комментарии:
1. Мне просто интересно узнать о вашем варианте использования. Зачем кому-то нужно обращаться к 40-тысячному пользователю на странице 2667, просто так, наугад?
2. Например, если я хочу, чтобы вы нашли своего пользователя в этом списке, и после того, как узнали, что ваша позиция почти в конце, вам нужно будет написать эту страницу от руки.
Ответ №1:
«доступ к 4782-й странице» — каков вариант использования для этого? «Разбивка на страницы» полезна для нескольких страниц, может быть, нескольких десятков страниц, но не тысяч.
[Next], [Prev], [First], [Last] полезны. Но если вам нужен случайный пробник, тогда назовите его [случайным] пробником, а не «страница 4782».
OFFSET
неэффективно. Вот обсуждение альтернативы: http://mysql.rjweb.org/doc.php/pagination
Тем временем добавьте INDEX(country, posts_count, id)
Комментарии:
1. Дело не в том, какой вариант использования для этого, потому что, как мы можем видеть по этой ссылке, Amazon делает это очень быстро, а также многие крупные компании (Zalando, Aliexpress .. и т.д.). Проблема в том, как эффективно решить ее в настоящее время. Ваша ссылка для обсуждения действительно полезна, когда у вас есть только один или два параметра для сортировки.
Ответ №2:
Один из способов добиться этого с помощью Elasticsearch — добавить линейно увеличивающееся поле (например sort_field
) к каждой из ваших записей (или используйте поле ID, если оно линейно увеличивается). Первое поле записи имеет значение 1, второе 2, третье 3 и т.д…
Затем, если вы отсортируете по этому полю в режиме возрастания, вы можете использовать эту search_after
функцию для прямого доступа к любой записи.
Например, если вам нужно получить доступ к 4782-й странице (т.Е. к записи 71730 и следующей), вы можете добиться этого следующим образом:
POST my-index/_search
{
"size": 15, <--- the page size
"sort": [
{
"sort_field": "asc" <--- properly ordering the records
}
],
"search_after": [ 71730 ] <--- direct access to the desired record/page
}
При определенных обстоятельствах также возможно ускорить сортировку, используя возможности сортировки по индексу.
Примечание: глубокая разбивка на страницы — это не то, для чего был создан Elasticsearch. Решение, описанное выше, работает, но может иметь некоторые недостатки (см. Комментарии) в зависимости от вашего контекста. Возможно, это не лучшая доступная технология для того, что вам нужно сделать.
Комментарии:
1. Итак, в конце вы добавляете новый столбец, просто чтобы настроить «рейтинг». Но, как я уже сказал, этот рейтинг меняется почти в режиме реального времени, и я думаю, что обновлять этот рейтинг каждый раз будет очень дорого. (Поправьте меня, если я ошибаюсь)
2. Тогда Elasticsearch — это не та технология, которую вы ищете. По сути, это поисковая система, а не база данных, и глубокое разбиение на страницы не является одним из ее приоритетов
3. Да, это то, что я подумал. Вот почему мне нужны некоторые идеи
4. Хорошо, но вы, вероятно, можете удалить
elasticsearch
тег, тогда