Как эффективно разбить на страницы более 10 миллионов записей

#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 тег, тогда