Какой лучший способ «перемешать» таблицу записей базы данных? - PullRequest
6 голосов
/ 06 января 2011

Скажите, что у меня есть таблица с кучей записей, которую я хочу случайным образом представить пользователям.Я также хочу, чтобы пользователи могли разбивать страницы на страницы и обратно, поэтому я должен соблюдать какой-то порядок, по крайней мере, на некоторое время.

Приложение в основном только AJAX и использует кэш для уже посещенных страниц,поэтому, даже если я всегда получаю случайные результаты, когда пользователь пытается вернуться, он получает предыдущую страницу, потому что она загружается из локального кэша.

Проблема в том, что если я возвращаю только случайные результатымогут быть некоторые дубликаты.Каждая страница содержит 6 результатов, поэтому, чтобы избежать этого, я должен был сделать что-то вроде WHERE id NOT IN (1,2,3,4 ...), где я бы поместил все ранее загруженные идентификаторы.

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

Альтернативным решением может быть создание еще одного столбца для упорядочивания записей, и shuffle это каждые введите здесь единицу времени .Проблема здесь в том, что мне нужно было бы установить случайное число из последовательности для каждой записи в таблице, которая бы принимала столько запросов, сколько существует записей.

Я использую Rails и MySQL, если этолюбой актуальности.

Ответы [ 3 ]

7 голосов
/ 06 января 2011

Попробуйте это:

mysql> create table t (i int);
mysql> insert into t values (1),(2),(3),(4),(5),(6);
mysql> select * from t order by rand(123) limit 2 offset 0;
+------+
| i    |
+------+
|    6 | 
|    4 | 
+------+
mysql> select * from t order by rand(123) limit 2 offset 2;
+------+
| i    |
+------+
|    2 | 
|    3 | 
+------+
mysql> select * from t order by rand(123) limit 2 offset 4;
+------+
| i    |
+------+
|    5 | 
|    1 | 
+------+

Обратите внимание, что функция rand () имеет начальное значение (123).Также обратите внимание, что если вы повторите три последних запроса, вы будете каждый раз получать один и тот же результат.

2 голосов
/ 06 января 2011

Если случайные результаты «для всех», а не для любого конкретного пользователя, то вы можете сделать что-то вроде этого: (Это для Postgres, должно работать с другими)

update mytable set sortorder = random() * 100000000;

select * from mytable order by sortorder, primarykeyid;

Поскольку случайные МОГУТ дублироватьвторичная сортировка по primarykeyid обеспечивает сортировке некоторую стабильность.

Вы можете делать это так часто, как вы хотите обновить кэш.Например, дать вам страницы абсолютного истечения, скажем, каждую минуту.Затем каждую минуту вы обновляете порядок сортировки и обслуживаете страницы в обычном режиме.

Если вы получаете запросы через окно обновления, то да, у вас есть шанс, что разные страницы получат одинаковые результаты.У вас также будет проблема, когда они нажимают «назад», они вполне могут не получить страницу, которая была у них раньше (поскольку она обновилась).

Вид сводится к тому, что является мотивацией для представления случайных данныхо том, насколько хорошо это будет работать.Это также зависит от объема данных и т. Д.

Но это удобный для кеша способ справиться с этим, если это важно для вас.Он также не имеет состояния (не требуется информация о сеансе).

2 голосов
/ 06 января 2011

Я бы сделал следующее (при условии последовательного числового первичного ключа):

  1. Создать случайное число и сохранить его в сеансе пользователя
  2. Когда пользователь просматривает данные, запрашивает общее количество строк
  3. Использование числа, хранящегося в сеансе, в качестве начального числа для создания одинакового «случайного» порядка идентификаторов для каждого запроса
  4. Пролистать идентификаторы и извлечь из базы данных только те записи, которые соответствуют этим идентификаторам.
...